using ImageMagick;
using IronPython.Runtime;
using Microsoft.VisualBasic.FileIO;
using Microsoft.Win32;
using NPOI.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using NPOI.XWPF.Model;
using NPOI.XWPF.UserModel;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Navigation;
using static QRCoder.QRCodeGenerator;
using ICell = NPOI.SS.UserModel.ICell;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils.NPOIHelp
{
    #region Word Help

    public class 格式文档管理器
    {
        public 格式文档管理器()
        {
        }

        public 格式文档管理器(string filePath)
        {
            using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                _文档 = new XWPFDocument(fs);
                fs.Close();
            }
        }

        public static 格式文档管理器 从文件创建(string filePath)
        {
            if (File.Exists(filePath) == false) return null;
            try
            {
                return new 格式文档管理器(filePath);
            }
            catch
            {
                return null;
            }
        }

        private XWPFDocument _文档 = new XWPFDocument();

        public XWPFDocument 文档
        {
            get { return _文档; }
        }

        public 格式段落 创建段落()
        {
            return new 格式段落(this._文档.CreateParagraph());
        }

        public 格式文档管理器 替换文本(string find, string replacement = "")
        {
            _文档.FindAndReplaceText(find, replacement);
            return this;
        }

        public 格式段落 取段落(int index)
        {
            if (index < 0 || index >= _文档.Paragraphs.Count) return null;

            return new 格式段落(_文档.Paragraphs[index]);
        }

        public List<格式段落> 段落集
        {
            get
            {
                if (_文档.Paragraphs == null || _文档.Paragraphs.Count <= 0) return null;

                var list = new List<格式段落>();

                foreach (var para in _文档.Paragraphs)
                {
                    list.Add(new 格式段落(para));
                }

                return list;
            }
        }

        /// <summary>
        /// 注意：此方法不支持自动 Markdown 基本语法解析。如果有此需要，请使用“插入基本格式段落”方法。
        /// </summary>
        /// <param name="text">源文本。</param>
        /// <param name="fontFamilyName">字体名。</param>
        /// <param name="fontSize">字号</param>
        /// <param name="isBold">是否加粗。</param>
        /// <param name="isItalic">是否倾斜。</param>
        /// <param name="underLineStyle">是否带下划线。</param>
        /// <param name="rgbColor">文本色彩。</param>
        /// <returns></returns>
        public 格式段落 插入格式段落(string text, string fontFamilyName = "宋体",
            double fontSize = 14, bool isBold = true, bool isItalic = false, string underLineStyle = "", string rgbColor = "000000")
        {
            var newPara = _文档.CreateParagraph();
            var newRun = newPara.CreateRun();
            newRun.SetText(text);
            newRun.FontFamily = fontFamilyName;
            newRun.FontSize = fontSize;
            newRun.IsBold = isBold;
            newRun.IsItalic = isItalic;
            var newRunSpan = new 格式片段(newRun);
            newRunSpan.置下划线(underLineStyle);
            newRunSpan.置色彩(rgbColor);

            return new 格式段落(newPara);
        }

        public 格式文档管理器 解析并插入试题(MarkdownEditor editor, string content = null, bool withGroupAnswer = false, string testpaper_title = "", bool ignoreAnswerPaper = false)
        {
            QuestionBuilder.ExportToWordDocument(editor, withGroupAnswer, this._文档, content, false, testpaper_title, ignoreAnswerPaper, true);
            return this;
        }

        public 格式文档管理器 插入分页符()
        {
            //this._文档.CreateParagraph().CreateRun().AddBreak();
            this._文档.CreateParagraph().IsPageBreak = true;
            return this;
        }

        public 格式文档管理器 解析片段并插入试题(MarkdownEditor editor, string header, string footer,
            bool byRegex = false, int startIndex = 0,
            bool ignoreCase = true, bool multiLine = true,
            bool withGroupAnswer = false, string testpaper_title = "", bool ignoreAnswerPaper = false)
        {
            var content = 纯文本处理器.取文本片段(editor.EditorBase.Text, header, footer, byRegex, startIndex, ignoreCase, multiLine);
            QuestionBuilder.ExportToWordDocument(editor, withGroupAnswer, this._文档, content, false, testpaper_title, ignoreAnswerPaper);
            return this;
        }

        public string 导出word样式表集()
        {
            var sb = new StringBuilder();
            sb.Append("\r\n；[ Word 样式表集 >>>\r\n");
            sb.Append(主标题样式.导出段落样式表());
            sb.Append(一级标题样式.导出段落样式表());
            sb.Append(二级标题样式.导出段落样式表());
            sb.Append(三级标题样式.导出段落样式表());
            sb.Append(四级标题样式.导出段落样式表());
            sb.Append(正文段落样式.导出段落样式表());
            sb.Append(默认段落样式.导出段落样式表());
            sb.Append("\r\n；] Word 样式表集\r\n");

            return sb.ToString();
        }

        public void 导入word样式表集(string text)
        {
            if (string.IsNullOrWhiteSpace(text)) return;

            var mainTitleStyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*一级标题段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*一级标题段落样式", true);
            if (string.IsNullOrWhiteSpace(mainTitleStyleText) == false)
            {
                主标题样式.导入段落样式表(mainTitleStyleText);
            }

            var level1StyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*一级标题段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*一级标题段落样式", true);
            if (string.IsNullOrWhiteSpace(level1StyleText) == false)
            {
                一级标题样式.导入段落样式表(level1StyleText);
            }

            var level2StyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*二级标题段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*二级标题段落样式", true);
            if (string.IsNullOrWhiteSpace(level2StyleText) == false)
            {
                二级标题样式.导入段落样式表(level2StyleText);
            }

            var level3StyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*三级标题段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*三级标题段落样式", true);
            if (string.IsNullOrWhiteSpace(level3StyleText) == false)
            {
                三级标题样式.导入段落样式表(level3StyleText);
            }

            var level4StyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*四级标题段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*四级标题段落样式", true);
            if (string.IsNullOrWhiteSpace(level4StyleText) == false)
            {
                四级标题样式.导入段落样式表(level4StyleText);
            }

            var normalStyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*正文段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*正文段落样式", true);
            if (string.IsNullOrWhiteSpace(normalStyleText) == false)
            {
                正文段落样式.导入段落样式表(normalStyleText);
            }

            var defaultStyleText = 纯文本处理器.取文本片段(text, @"\r\n[;；][ 　\t]*[\(（][ 　\t]*默认段落样式[ 　\t]*>*", @"\r\n[;；][ 　\t]*[\)）][ 　\t]*默认段落样式", true);
            if (string.IsNullOrWhiteSpace(defaultStyleText) == false)
            {
                默认段落样式.导入段落样式表(defaultStyleText);
            }
        }

        public 段落样式 主标题样式 = new 段落样式()
        {
            样式名 = "主标题段落样式",
            字体名 = "SimSun",
            字号 = 22, // 二号字
            加粗 = true,
            对齐方式 = "center",
            首行缩进 = 0,
            段后磅值 = 11,
            行间距磅值 = 32,
        };

        public 格式段落 插入主标题(string title_text)
        {
            var 新段落 = 插入格式段落(title_text, 主标题样式.字体名, 主标题样式.字号, 主标题样式.加粗, 主标题样式.倾斜, 主标题样式.下划线, 主标题样式.色彩串);
            新段落.置首行缩进字符数(主标题样式.首行缩进);
            新段落.置对齐(主标题样式.对齐方式);
            新段落.置段前磅间距(主标题样式.段前磅值);
            新段落.置段后磅间距(主标题样式.段后磅值);
            新段落.置磅行间距(主标题样式.行间距磅值);
            新段落.置删除线(主标题样式.删除线);
            return 新段落;
        }

        public 段落样式 一级标题样式 { get; set; } = new 段落样式
        {
            样式名 = "一级标题段落样式",
            字体名 = "黑体",
            字号 = 16,  // 三号字
            行间距磅值 = 28,   // 通常公文是固定值 28 磅
            首行缩进 = 4,   // 四个半角字符宽度
        };

        public 格式段落 插入一级标题(int num, string para_text)
        {
            var num_text = num > 0 ? (DateTimeConverter.YearToCn(num) + "、") : "";

            var 新段落 = 插入格式段落(num_text + para_text, 一级标题样式.字体名, 一级标题样式.字号, 一级标题样式.加粗, 一级标题样式.倾斜, 一级标题样式.下划线, 一级标题样式.色彩串);
            新段落.置首行缩进字符数(一级标题样式.首行缩进);
            新段落.置对齐(一级标题样式.对齐方式);
            新段落.置段前磅间距(一级标题样式.段前磅值);
            新段落.置段后磅间距(一级标题样式.段后磅值);
            新段落.置磅行间距(一级标题样式.行间距磅值);
            新段落.置删除线(一级标题样式.删除线);
            return 新段落;
        }

        public 段落样式 二级标题样式 { get; set; } = new 段落样式
        {
            样式名 = "二级标题段落样式",
            字体名 = "楷体",
            字号 = 16,  // 三号字
            行间距磅值 = 28,   // 通常公文是固定值 28 磅
            首行缩进 = 4,   // 四个半角字符宽度
            加粗 = true,
        };

        public 格式段落 插入二级标题(int num, string para_text)
        {
            var num_text = num > 0 ? ("（" + DateTimeConverter.YearToCn(num) + "）") : "";

            var 新段落 = 插入格式段落(num_text + para_text, 二级标题样式.字体名, 二级标题样式.字号, 二级标题样式.加粗, 二级标题样式.倾斜, 二级标题样式.下划线, 二级标题样式.色彩串);
            新段落.置首行缩进字符数(二级标题样式.首行缩进);
            新段落.置对齐(二级标题样式.对齐方式);
            新段落.置段前磅间距(二级标题样式.段前磅值);
            新段落.置段后磅间距(二级标题样式.段后磅值);
            新段落.置磅行间距(二级标题样式.行间距磅值);
            新段落.置删除线(二级标题样式.删除线);
            return 新段落;
        }

        public 段落样式 三级标题样式 { get; set; } = new 段落样式
        {
            样式名 = "三级标题段落样式",
            字体名 = "仿宋",
            字号 = 16,  // 三号字
            行间距磅值 = 28,   // 通常公文是固定值 28 磅
            首行缩进 = 4,   // 四个半角字符宽度
        };

        public 格式段落 插入三级标题(int num, string para_text)
        {
            var num_text = num > 0 ? (num + ". ") : "";

            var 新段落 = 插入格式段落(num_text + para_text, 三级标题样式.字体名, 三级标题样式.字号, 三级标题样式.加粗, 三级标题样式.倾斜, 三级标题样式.下划线, 三级标题样式.色彩串);
            新段落.置首行缩进字符数(三级标题样式.首行缩进);
            新段落.置对齐(三级标题样式.对齐方式);
            新段落.置段前磅间距(三级标题样式.段前磅值);
            新段落.置段后磅间距(三级标题样式.段后磅值);
            新段落.置磅行间距(三级标题样式.行间距磅值);
            新段落.置删除线(三级标题样式.删除线);
            return 新段落;
        }

        /// <summary>
        /// 默认情况下，三级、四级标题样式相同，仅标号方式不同。
        /// </summary>
        public 段落样式 四级标题样式 { get; set; } = new 段落样式
        {
            样式名 = "四级标题段落样式",
            字体名 = "仿宋",
            字号 = 16,  // 三号字
            行间距磅值 = 28,   // 通常公文是固定值 28 磅
            首行缩进 = 4,   // 四个半角字符宽度
        };

        public 格式段落 插入四级标题(int num, string para_text)
        {
            var num_text = num > 0 ? ("（" + num + "）") : "";

            var 新段落 = 插入格式段落(num_text + para_text, 四级标题样式.字体名, 四级标题样式.字号, 四级标题样式.加粗, 四级标题样式.倾斜, 四级标题样式.下划线, 四级标题样式.色彩串);
            新段落.置首行缩进字符数(四级标题样式.首行缩进);
            新段落.置对齐(四级标题样式.对齐方式);
            新段落.置段前磅间距(四级标题样式.段前磅值);
            新段落.置段后磅间距(四级标题样式.段后磅值);
            新段落.置磅行间距(四级标题样式.行间距磅值);
            新段落.置删除线(四级标题样式.删除线);
            return 新段落;
        }

        public 段落样式 正文段落样式 { get; set; } = new 段落样式
        {
            样式名 = "正文段落样式",
            字体名 = "仿宋",
            字号 = 16,  // 三号字
            行间距磅值 = 28,   // 通常公文是固定值 28 磅
            首行缩进 = 4,   // 四个半角字符宽度
        };

        public 格式段落 插入正文段落(string para_text)
        {
            var 新段落 = 插入格式段落(para_text, 正文段落样式.字体名, 正文段落样式.字号, 正文段落样式.加粗, 正文段落样式.倾斜, 正文段落样式.下划线, 正文段落样式.色彩串);
            新段落.置首行缩进字符数(正文段落样式.首行缩进);
            新段落.置对齐(正文段落样式.对齐方式);
            新段落.置段前磅间距(正文段落样式.段前磅值);
            新段落.置段后磅间距(正文段落样式.段后磅值);
            新段落.置磅行间距(正文段落样式.行间距磅值);
            新段落.置删除线(正文段落样式.删除线);
            return 新段落;
        }

        public 段落样式 默认段落样式 = new 段落样式()
        {
            样式名 = "默认段落样式",
            字体名 = "宋体",
            字号 = 12,          // 小四号字
            行间距磅值 = 25,    // 通常公文是三号字配固定值 28 磅，但这里是小四号，没必要那么大。
            首行缩进 = 4,   // 四个半角字符宽度
        };

        /// <summary>
        /// 按指定样式插入段落。
        /// </summary>
        /// <param name="para_text">新段落中的文本。</param>
        /// <param name="para_Style">段落样式。如果传入 null，会自动使用默认段落样式。</param>
        /// <returns></returns>
        public 格式段落 按样式插入段落(string para_text, 段落样式 para_Style = null)
        {
            if (para_Style == null)
                para_Style = 默认段落样式;

            var 新段落 = 插入格式段落(para_text, para_Style.字体名, para_Style.字号, para_Style.加粗, para_Style.倾斜, para_Style.下划线, para_Style.色彩串);
            新段落.置首行缩进字符数(para_Style.首行缩进);
            新段落.置对齐(para_Style.对齐方式);
            新段落.置段前磅间距(para_Style.段前磅值);
            新段落.置段后磅间距(para_Style.段后磅值);
            新段落.置磅行间距(para_Style.行间距磅值);
            新段落.置删除线(para_Style.删除线);
            return 新段落;
        }

        /// <summary>
        /// 注意：text 中不应有换行。
        /// </summary>
        /// <param name="text">源文本。</param>
        /// <param name="fillBlankMode">是否启用填空模式。</param>
        /// <param name="fontName">字体名。</param>
        /// <param name="fontSize">字号。</param>
        /// <param name="fstLineIndent">段落首行缩进（单位是字符数）。</param>
        /// <param name="mdFilePath">Markdown 文件路径（需要根据这个路径计算相对路径的图像链接指向的真实图像位置）。</param>
        /// <returns>返回生成的 格式段落 列表。以便进一步设置格式。</returns>
        public List<格式段落> 插入基本格式段落(string text, bool fillBlankMode = false,
            string fontName = "宋体", double fontSize = 11, int fstLineIndent = 0, string mdFilePath = null)
        {
            if (string.IsNullOrEmpty(text)) return null;

            var lines = text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            var list = new List<格式段落>();

            foreach (var line in lines)
            {
                if (string.IsNullOrEmpty(line)) continue;

                var pieces = 格式解析器.基本格式解析(line);
                var normalCount = 0;
                foreach (var piece in pieces)
                {
                    if (piece.IsMartchText == false) normalCount++;
                }
                if (normalCount <= 0) continue;  // 只有格式符的段落无意义。

                var newPara = _文档.CreateParagraph();
                var formatPara = new 格式段落(newPara);

                list.Add(formatPara);

                foreach (var piece in pieces)
                {
                    if (piece.IsMartchText) continue;
                    var newRun = newPara.CreateRun();
                    var newFormatRun = new 格式片段(newRun);
                    newFormatRun.置字体(fontName);
                    newFormatRun.置字号(fontSize);

                    if (piece.AppendInfos != null && piece.AppendInfos.Count > 0)
                    {
                        foreach (var format in piece.AppendInfos)
                        {
                            switch (format)
                            {
                                case "加粗":
                                case "Html加粗":
                                case "Html强强调":  // strong 标签

                                    {
                                        newRun.IsBold = true;
                                        break;
                                    }
                                case "Html强调":  // em 标签
                                case "倾斜":
                                    {
                                        newRun.IsItalic = true;
                                        break;
                                    }
                                case "代码块":
                                    {
                                        if (fillBlankMode)
                                        {
                                            newFormatRun.置色彩("ff0000");
                                            // newFormatRun.置下划线("single");
                                        }
                                        else
                                        {
                                            newFormatRun.置色彩("0000ff");
                                            newFormatRun.置下划线("single");
                                        }
                                        break;
                                    }
                                case "下划线":
                                    {
                                        newFormatRun.置下划线("single");
                                        break;
                                    }
                                case "删除线":
                                    {
                                        newFormatRun.置删除线(true);
                                        break;
                                    }
                                case "快捷图标":
                                    {
                                        if (string.IsNullOrEmpty(piece.SourceText)) break;

                                        var shortName = piece.SourceText.Replace("/", "\\").Replace("<-&#95;->", "_");
                                        if (shortName.EndsWith(".")) shortName += "png";

                                        var path = Globals.PathOfWorkspace + "Images~\\" + shortName;
                                        if (File.Exists(path) == false) break;

                                        formatPara.插入图像文件(path, (int)(fontSize * 0.8));
                                        break;
                                    }
                                case "图像链接":
                                    {
                                        if (string.IsNullOrWhiteSpace(mdFilePath)) break;

                                        if (mdFilePath.ToLower().StartsWith(Globals.PathOfWorkspace.ToLower()) == false)
                                            throw new Exception("提供的 Markdown 文件路径不是当前工作区下有有效路径。");

                                        var imgFilePath = piece.SourceText;

                                        var reg = new Regex(@"[ 　\t]{1,}('.*'|"".*"")[ 　\t]*$");
                                        var match = reg.Match(imgFilePath);
                                        if (match.Success)
                                        {
                                            imgFilePath = imgFilePath.Substring(0, match.Index);
                                        }

                                        if (string.IsNullOrWhiteSpace(imgFilePath)) break;

                                        var realImgFilePath = Utils.ImageLinkTool.GetRealPathFromRelativePath(imgFilePath, mdFilePath);

                                        if (System.IO.File.Exists(realImgFilePath))
                                        {
                                            formatPara.插入图像文件(realImgFilePath, (int)(fontSize * 0.8));
                                        }
                                        // 没有当前编辑器路径参数，无法将相对路径转换为图像的绝对路径，无法实现。
                                        break;
                                    }
                            }
                        }

                        if (piece.AppendInfos.Contains("快捷图标") == false && piece.AppendInfos.Contains("图像链接") == false)
                        {
                            if (fillBlankMode && piece.AppendInfos.Contains("代码块"))
                            {
                                var txtWidth = Utils.Text.GetTextWidth(piece.SourceText);
                                var txt = new string('_', txtWidth);
                                newRun.SetText(txt.Replace("\\_", "_").Replace("\\*", "*"));
                            }
                            else
                            {
                                newRun.SetText(piece.SourceText.Replace("\\_", "_").Replace("\\*", "*"));
                            }
                        }
                    }
                    else
                    {
                        newRun.SetText(piece.SourceText.Replace("\\_", "_").Replace("\\*", "*"));
                    }
                }

                if (fstLineIndent > 0 && newPara.Runs.Count > 0)
                {
                    formatPara.置首行缩进字符数(fstLineIndent);
                    // 放在后面才能获取到字号，从而才能准确地取到首行缩进字符宽度。
                }
            }

            return list;
        }

        public List<Question> 解析试题(MarkdownEditor editor)
        {
            var errorMsg = new StringBuilder();
            var questions = QuestionBuilder.BuildQuestions(editor, errorMsg, true);
            if (questions == null || questions.Count <= 0)
            {
                LMessageBox.ShowWarning("未指定编辑器或编辑器中无试题文本！");
                return null;
            }

            var qcount = 0;
            foreach (var q in questions)
            {
                if (q.Type != QuestionType.Text)
                    qcount++;
            }

            if (qcount <= 0)
            {
                LMessageBox.ShowWarning("没能在当前演示界面中找到试题，无法执行。");
                return null;
            }

            return questions;
        }

        /// <summary>
        /// 为兼容旧代码保留它——不便于在智能提示中选择（易混淆）。
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public 文件 保存(string filePath)
        {
            try
            {
                var fileInfo = new FileInfo(filePath);
                if (fileInfo.Directory.Exists == false)
                    fileInfo.Directory.Create();

                using (var sw = System.IO.File.Create(filePath))
                {
                    this._文档.Write(sw);
                }
                return new 文件(filePath);
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning("[auto]保存失败！异常消息如下：\r\n" + ex.Message);
                return null;
            }
        }

        public 文件 保存格式文档(string filePath)
        {
            return 保存(filePath);
        }

        public 格式文档管理器 置纸型(string paperSizeMark)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;
            if (m_SectPr == null)
            {
                m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                body.sectPr = m_SectPr;
            }

            var paperSize = GetPaperSizeTwips(paperSizeMark);

            switch (m_SectPr.pgSz.orient)
            {
                case ST_PageOrientation.landscape:  // 横向
                    {
                        m_SectPr.pgSz.h = (ulong)Math.Min(paperSize.Height, paperSize.Width);
                        m_SectPr.pgSz.w = (ulong)Math.Max(paperSize.Height, paperSize.Width);
                        break;
                    }
                default:  // 纵向
                    {
                        m_SectPr.pgSz.h = (ulong)Math.Max(paperSize.Height, paperSize.Width);
                        m_SectPr.pgSz.w = (ulong)Math.Min(paperSize.Height, paperSize.Width);
                        break;
                    }
            }
            return this;
        }

        public 格式文档管理器 置格式文档纸型(string paperSizeMark)
        {
            return 置纸型(paperSizeMark);
        }

        public 格式文档管理器 置页面类型(页面类型 pageType = 页面类型.PageA4)
        {
            switch (pageType)
            {
                case 页面类型.PageA4:
                    return 置页面厘米尺寸(29.7, 21);
                case 页面类型.Page6号信封:
                    return 置页面厘米尺寸(23, 12);
                case 页面类型.PageC5信封:
                    return 置页面厘米尺寸(22.9, 16.2);
                case 页面类型.Page9号信封:
                    return 置页面厘米尺寸(32.4, 22.9);
                case 页面类型.PageA3:
                    return 置页面厘米尺寸(42, 29.7);
                case 页面类型.Page8开:
                    return 置页面厘米尺寸(36.8, 26);
                case 页面类型.Page16开:
                    return 置页面厘米尺寸(26, 18.4);
                case 页面类型.Page大16开:
                    return 置页面厘米尺寸(28.5, 21);
                case 页面类型.Page32开:
                    return 置页面厘米尺寸(18.4, 13);
                case 页面类型.Page大32开:
                    return 置页面厘米尺寸(20.3, 14);
                case 页面类型.Page3号信封:
                    return 置页面厘米尺寸(17.6, 12.5);
                case 页面类型.PageDL信封:
                    return 置页面厘米尺寸(22, 11);
                case 页面类型.Page信纸:
                    return 置页面厘米尺寸(27.94, 21.59);
                case 页面类型.Page法律专用纸:
                    return 置页面厘米尺寸(35.56, 21.59);
                case 页面类型.PageExecutive:
                    return 置页面厘米尺寸(26.67, 18.41);
                case 页面类型.PageA5:
                    return 置页面厘米尺寸(21, 14.8);
                case 页面类型.PageB5JIS:
                    return 置页面厘米尺寸(25.7, 18.2);
                case 页面类型.Page10号信封:
                    return 置页面厘米尺寸(24.13, 10.47);
                case 页面类型.PageB5信封:
                    return 置页面厘米尺寸(25, 17.6);
                case 页面类型.PageMonarch信封:
                    return 置页面厘米尺寸(19.05, 9.84);
                case 页面类型.Page日式明信片:
                    return 置页面厘米尺寸(14.8, 10);
                case 页面类型.PageExecutiveJIS:
                    return 置页面厘米尺寸(32.99, 21.59);
                case 页面类型.Page16K:
                    return 置页面厘米尺寸(19.68, 27.3);
                default:
                    return 置页面厘米尺寸(29.7, 21);
            }
        }

        public 格式文档管理器 置格式文档页面类型(页面类型 pageType = 页面类型.PageA4)
        {
            return 置页面类型(pageType);
        }

        /// <summary>
        /// 设置页面尺寸。
        /// 注意：此方法会自动根据纸张方向决定长边、短边。所以两个参数的顺序**无关紧要**。
        /// </summary>
        /// <param name="side1Width">一条边的长度，单位是缇（twip，1/20 磅，即 1/1440 英寸）。</param>
        /// <param name="side2Width">另一条边的长度，单位是缇（twip，1/20 磅，即 1/1440 英寸）。</param>
        /// <returns></returns>
        public 格式文档管理器 置页面尺寸(ulong side1Width, ulong side2Width)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;
            if (m_SectPr == null)
            {
                m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                body.sectPr = m_SectPr;
            }

            switch (m_SectPr.pgSz.orient)
            {
                case ST_PageOrientation.landscape:  // 横向
                    {
                        m_SectPr.pgSz.h = (ulong)Math.Min(side1Width, side2Width);
                        m_SectPr.pgSz.w = (ulong)Math.Max(side1Width, side2Width);
                        break;
                    }
                default:  // 纵向
                    {
                        m_SectPr.pgSz.h = (ulong)Math.Max(side1Width, side2Width);
                        m_SectPr.pgSz.w = (ulong)Math.Min(side1Width, side2Width);
                        break;
                    }
            }
            return this;
        }

        public 格式文档管理器 置页面缇尺寸(ulong side1Width, ulong side2Width)
        {
            return 置页面尺寸(side1Width, side2Width);
        }

        public 格式文档管理器 置页面厘米尺寸(double cm1, double cm2)
        {
            return 置页面尺寸((ulong)(cm1 * 567), (ulong)(cm2 * 567));
        }

        public 格式文档管理器 置页面毫米尺寸(double mm1, double mm2)
        {
            return 置页面尺寸((ulong)(mm1 * 56.7), (ulong)(mm2 * 56.7));
        }

        public 格式文档管理器 置方向(string orient)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;
            if (m_SectPr == null)
            {
                m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                body.sectPr = m_SectPr;
            }

            if (string.IsNullOrWhiteSpace(orient))
            {
                orient = "h";
            }

            var h = m_SectPr.pgSz.h;
            var w = m_SectPr.pgSz.w;

            switch (orient.ToLower())
            {
                case "v":
                case "vertical":
                case "纵":
                case "纵向":
                    {
                        m_SectPr.pgSz.orient = ST_PageOrientation.portrait;
                        m_SectPr.pgSz.h = (ulong)Math.Max(h, w);
                        m_SectPr.pgSz.w = (ulong)Math.Min(h, w);
                        break;
                    }
                default:
                    {
                        m_SectPr.pgSz.orient = ST_PageOrientation.landscape;
                        m_SectPr.pgSz.h = (ulong)Math.Min(h, w);
                        m_SectPr.pgSz.w = (ulong)Math.Max(h, w);
                        break;
                    }
            }
            return this;
        }

        public 格式文档管理器 置页面方向(string orient)
        {
            return 置方向(orient);
        }

        public 格式文档管理器 置分栏数(int cols)
        {
            try
            {
                var body = this._文档.Document.body;
                var m_SectPr = body.sectPr;
                if (m_SectPr == null)
                {
                    m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                    body.sectPr = m_SectPr;
                }

                var columns = m_SectPr.cols;
                columns.num = cols.ToString();
                return this;
            }
            catch (Exception ex)
            {
                LMessageBox.Show(ex.Message);
                return this;
            }
        }

        public 格式文档管理器 置分栏(int cols)
        {
            return 置分栏数(cols);
        }

        /// <summary>
        /// 设置页面四边边距，单位是厘米。
        /// </summary>
        /// <param name="left">页面左边距。</param>
        /// <param name="top">页面上边距。</param>
        /// <param name="right">页面右边距。</param>
        /// <param name="bottom">页面下边距。</param>
        public 格式文档管理器 置页边距(double left, double top, double right, double bottom)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;
            if (m_SectPr == null)
            {
                m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                body.sectPr = m_SectPr;
            }

            var newLeft = (ulong)(left * 567);
            var newTop = (ulong)(top * 567);
            var newRight = (ulong)(right * 567);
            var newBottom = (ulong)(bottom * 567);

            m_SectPr.pgMar.left = (newLeft < 1 ? 1 : newLeft);
            m_SectPr.pgMar.right = (newRight < 1 ? 1 : newRight);
            m_SectPr.pgMar.top = (newTop < 1 ? 1 : newTop);
            m_SectPr.pgMar.bottom = (newBottom < 1 ? 1 : newBottom);
            return this;
        }

        /// <summary>
        /// 单位是厘米。
        /// </summary>
        /// <param name="width"></param>
        public 格式文档管理器 置栏间距(ulong width)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;
            if (m_SectPr == null)
            {
                m_SectPr = new NPOI.OpenXmlFormats.Wordprocessing.CT_SectPr();
                body.sectPr = m_SectPr;
            }

            var columns = m_SectPr.cols;
            columns.space = width * 567;  // 这个单位是缇，1缇为 1/567厘米。
            return this;
        }

        /// <summary>
        /// 这个方法从纸张名称返回纵向的尺寸，单位是缇（twip）。
        /// 1缇等于1/1440英寸或1/567厘米。
        /// </summary>
        /// <param name="paperSizeMark"></param>
        /// <returns></returns>
        public System.Windows.Size GetPaperSizeTwips(string paperSizeMark)
        {
            if (string.IsNullOrWhiteSpace(paperSizeMark))
            {
                paperSizeMark = "a4";
            }

            switch (paperSizeMark.ToLower())
            {
                case "e6":
                case "6号信封":
                    {
                        return new System.Windows.Size() { Height = 23 * 567, Width = 12 * 567 };
                    }
                case "e7":
                case "7号信封":
                    {
                        return new System.Windows.Size() { Height = 22.9 * 567, Width = 16.2 * 567 };
                    }
                case "e9":
                case "9号信封":
                    {
                        return new System.Windows.Size() { Height = 32.4 * 567, Width = 22.9 * 567 };
                    }
                case "a3":
                    {
                        return new System.Windows.Size() { Height = 42 * 567, Width = 29.7 * 567 };
                    }
                case "8k":
                case "8开":
                    {
                        return new System.Windows.Size() { Height = 36.8 * 567, Width = 26 * 567 };
                    }
                case "16k":
                case "16开":
                    {
                        return new System.Windows.Size() { Height = 26 * 567, Width = 18.4 * 567 };
                    }
                case "b16k":
                case "big16k":
                case "大16开":
                    {
                        return new System.Windows.Size() { Height = 28.5 * 567, Width = 21 * 567 };
                    }
                case "32k":
                case "32开":
                    {
                        return new System.Windows.Size() { Height = 18.4 * 567, Width = 13 * 567 };
                    }
                case "b32k":
                case "big32k":
                case "大32开":
                    {
                        return new System.Windows.Size() { Height = 20.3 * 567, Width = 14 * 567 };
                    }
                case "e3":
                case "3号信封":
                    {
                        return new System.Windows.Size() { Height = 17.6 * 567, Width = 12.5 * 567 };
                    }
                case "e5":
                case "5号信封":
                    {
                        return new System.Windows.Size() { Height = 22 * 567, Width = 11 * 567 };
                    }
                case "e":
                case "信纸":
                    {
                        return new System.Windows.Size() { Height = 27.94 * 567, Width = 21.59 * 567 };
                    }
                case "t":
                case "tabloid":
                case "小报":
                    {
                        return new System.Windows.Size() { Height = 43.18 * 567, Width = 27.94 * 567 };
                    }
                case "l":
                case "law":
                case "法律专用纸":
                    {
                        return new System.Windows.Size() { Height = 35.56 * 567, Width = 21.59 * 567 };
                    }
                case "s":
                case "statement":
                case "声明":
                    {
                        return new System.Windows.Size() { Height = 21.59 * 567, Width = 13.97 * 567 };
                    }
                case "ex":
                case "exe":
                case "executive":
                case "行政用纸":
                    {
                        return new System.Windows.Size() { Height = 26.67 * 567, Width = 18.41 * 567 };
                    }
                case "a5":
                    {
                        return new System.Windows.Size() { Height = 21 * 567, Width = 14.8 * 567 };
                    }
                case "b4":
                case "b4j":
                case "b4jis":
                    {
                        return new System.Windows.Size() { Height = 36.4 * 567, Width = 25.7 * 567 };
                    }
                case "b5":
                case "b5j":
                case "b5jis":
                    {
                        return new System.Windows.Size() { Height = 25.7 * 567, Width = 18.2 * 567 };
                    }
                default:  // a4
                    {
                        return new System.Windows.Size() { Height = 29.7 * 567, Width = 21 * 567 };
                    }
            }
        }

        public void ConvertImageSize(ref double width, ref double height)
        {
            var hc = height * 2.54 / 72;
            var wc = width * 2.54 / 72;

            width = wc * 360000;
            height = hc * 360000;
        }

        /// <summary>
        /// 图像单独出现在一个段落中。
        /// </summary>
        /// <param name="path"></param>
        public 格式文档管理器 插入图像文件(string imagePath, double? custom_width = null, double? custom_height = null)
        {
            if (System.IO.File.Exists(imagePath))
            {
                var fi = new FileInfo(imagePath);
                int pictureType = -1;
                switch (fi.Extension.ToLower().Trim(new char[] { '.', ' ', '　', '\t' }))
                {
                    case "emf":
                        {
                            pictureType = 2; break;
                        }
                    case "wmf":
                        {
                            pictureType = 3; break;

                        }
                    case "pict":
                        {
                            pictureType = 4; break;
                        }
                    case "jpg":
                    case "jpeg":
                        {
                            pictureType = 5; break;
                        }
                    case "png":
                        {
                            pictureType = 6; break;
                        }
                    case "dib":
                        {
                            pictureType = 7; break;
                        }
                    case "gif":
                        {
                            pictureType = 8; break;
                        }
                    case "tif":
                    case "tiff":
                        {
                            pictureType = 9; break;
                        }
                    case "eps":
                        {
                            pictureType = 10; break;
                        }
                    case "bmp":
                        {
                            pictureType = 11; break;
                        }
                    case "wpg":
                        {
                            pictureType = 12; break;
                        }
                    case "svg":
                        {
                            pictureType = 13; break;
                        }
                    default:
                        {
                            throw new Exception("不能识别此图像文件格式！");
                        }
                }

                double width, height;
                using (var gfs1 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    if (custom_width == null && custom_height == null)
                    {
                        var img = System.Drawing.Image.FromStream(gfs1);
                        width = img.Width;
                        height = img.Height;
                    }
                    else if (custom_height != null && custom_width != null)
                    {
                        width = custom_width.Value;
                        height = custom_height.Value;
                    }
                    else
                    {
                        var img = System.Drawing.Image.FromStream(gfs1);
                        width = (custom_width != null ? custom_width.Value : img.Width);
                        height = (custom_height != null ? custom_height.Value : img.Height);
                    }
                    ConvertImageSize(ref width, ref height);
                }

                var ms = LFile.ReadImageToMemoryStream(imagePath);

                // NPOI.XWPF.UserModel.PictureType
                var c_p = _文档.Document.body.AddNewP();

                c_p.AddNewPPr().AddNewJc().val = NPOI.OpenXmlFormats.Wordprocessing.ST_Jc.center;
                var cp = new XWPFParagraph(c_p, _文档);
                cp.SetSpacingBetween(1, LineSpacingRule.AUTO);
                var cr = cp.CreateRun();
                cr.AddPicture(ms, pictureType, "img", (int)width, (int)height);  // 默认14cm，1cm = 360000 EMUS（English Metric Unit）;
                c_p.AddNewPPr().AddNewSpacing().lineRule = ST_LineSpacingRule.auto;
                cp.IndentationFirstLine = 0;
            }
            else
            {
                LMessageBox.ShowWarning("下列路径指示的图像文件不存在：\r\n" + imagePath);
            }
            return this;
        }

        public 格式文档管理器 填充图像到页面(string imagePath)
        {
            var body = this._文档.Document.body;
            var m_SectPr = body.sectPr;

            var w = m_SectPr.pgSz.w - m_SectPr.pgMar.left - m_SectPr.pgMar.right;
            var h = m_SectPr.pgSz.h - m_SectPr.pgMar.top - m_SectPr.pgMar.bottom;

            if (w < 10) w = 10;
            if (h < 10) w = 10;

            w /= 20;
            h /= 20;

            return 插入图像文件(imagePath, w, h);
        }

        public 格式文档管理器 插入页眉(string pageHeaderText, string align)
        {
            if (string.IsNullOrWhiteSpace(pageHeaderText)) return this;
            if (string.IsNullOrWhiteSpace(align))
                align = "left";

            XWPFHeaderFooterPolicy policy = _文档.CreateHeaderFooterPolicy();
            XWPFHeader header = policy.CreateHeader(XWPFHeaderFooterPolicy.DEFAULT);  // EVEN 是偶数页
            var cpHeader = header.CreateParagraph();
            cpHeader.VerticalAlignment = NPOI.XWPF.UserModel.TextAlignment.CENTER;

            switch (align.ToLower())
            {
                case "l":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        cpHeader.Alignment = ParagraphAlignment.LEFT;
                        break;
                    }
                case "r":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        cpHeader.Alignment = ParagraphAlignment.RIGHT;
                        break;
                    }
                default:
                    {
                        cpHeader.Alignment = ParagraphAlignment.CENTER;
                        break;
                    }
            }

            cpHeader.CreateRun().SetText(pageHeaderText);
            cpHeader.BorderBottom = Borders.Single;
            return this;
        }

        public 格式文档管理器 插入页脚(string pageFooterText, string align)
        {
            if (string.IsNullOrWhiteSpace(pageFooterText)) return this;
            if (string.IsNullOrWhiteSpace(align))
                align = "left";

            XWPFHeaderFooterPolicy policy = _文档.CreateHeaderFooterPolicy();
            XWPFFooter footer = policy.CreateFooter(XWPFHeaderFooterPolicy.DEFAULT);
            var cpFooter = footer.CreateParagraph();
            cpFooter.VerticalAlignment = NPOI.XWPF.UserModel.TextAlignment.CENTER;

            switch (align.ToLower())
            {
                case "l":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        cpFooter.Alignment = ParagraphAlignment.LEFT;
                        break;
                    }
                case "r":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        cpFooter.Alignment = ParagraphAlignment.RIGHT;
                        break;
                    }
                default:
                    {
                        cpFooter.Alignment = ParagraphAlignment.CENTER;
                        break;
                    }
            }

            cpFooter.CreateRun().SetText(pageFooterText);
            cpFooter.BorderTop = Borders.Single;
            return this;
        }

        public 格式表格 插入表格(int rows, int columns)
        {
            return new 格式表格(this._文档.CreateTable(rows, columns));
        }

        public 格式表格 创建表格(int rows, int columns)
        {
            return new 格式表格(this._文档.CreateTable(rows, columns));
        }

        /// <summary>
        /// 实在找不到 Ct_TextBox 的用法。所以用只有一格的表格来代替！
        /// </summary>
        public 格式表格 插入文本框()
        {
            return new 格式表格(this._文档.CreateTable(1, 1));
        }

        public void Example(string path)
        {
            //Create document
            XWPFDocument doc = new XWPFDocument();
            XWPFParagraph para = doc.CreateParagraph();
            XWPFRun run = para.CreateRun();
            run.SetText("FileFomrat.com");

            doc.Document.body.sectPr = new CT_SectPr();
            CT_SectPr secPr = doc.Document.body.sectPr;

            //Create header and set its text
            CT_Hdr header = new CT_Hdr();
            //header.AddNewP().AddNewR().AddNewT().Value = "FileFormat.com";
            var headerParagraph = header.AddNewP();
            var paragraphRun = headerParagraph.AddNewR();
            var paragraphText = paragraphRun.AddNewT();
            paragraphText.Value = "FileFormat.com - An Open-source File Format API Guide For Developers";
            CT_PPr headerPPR = headerParagraph.AddNewPPr();
            CT_Jc headerAlign = headerPPR.AddNewJc();
            headerAlign.val = NPOI.OpenXmlFormats.Wordprocessing.ST_Jc.center;

            //Create footer and set its text
            CT_Ftr footer = new CT_Ftr();
            CT_P footerParagraph = footer.AddNewP();
            NPOI.OpenXmlFormats.Wordprocessing.CT_R ctr = footerParagraph.AddNewR();
            CT_Text ctt = ctr.AddNewT();
            ctt.Value = "CopyRight (C) 2023";
            CT_PPr ppr = footerParagraph.AddNewPPr();
            CT_Jc align = ppr.AddNewJc();
            align.val = NPOI.OpenXmlFormats.Wordprocessing.ST_Jc.center;

            //Create the relation of header
            XWPFRelation relation1 = XWPFRelation.HEADER;
            XWPFHeader myHeader = (XWPFHeader)doc.CreateRelationship(relation1, XWPFFactory.GetInstance(), doc.HeaderList.Count + 1);

            //Create the relation of footer
            XWPFRelation relation2 = XWPFRelation.FOOTER;
            XWPFFooter myFooter = (XWPFFooter)doc.CreateRelationship(relation2, XWPFFactory.GetInstance(), doc.FooterList.Count + 1);

            //Set the header
            myHeader.SetHeaderFooter(header);
            CT_HdrFtrRef myHeaderRef = secPr.AddNewHeaderReference();
            myHeaderRef.type = ST_HdrFtr.@default;
            myHeaderRef.id = myHeader.GetXWPFDocument().GetRelationId(myHeader); // = myHeader.GetPackageRelationship().Id;

            //Set the footer
            myFooter.SetHeaderFooter(footer);
            CT_HdrFtrRef myFooterRef = secPr.AddNewFooterReference();
            myFooterRef.type = ST_HdrFtr.@default;
            myFooterRef.id = myFooter.GetXWPFDocument().GetRelationId(myFooter);//myFooter.GetPackageRelationship().Id;

            //Save the file
            using (FileStream stream = File.Create(path))
            {
                doc.Write(stream);
            }
        }

        public List<格式表格> 格式表集
        {
            get
            {
                var tblArray = this._文档.Document.body.GetTblArray();
                if (tblArray == null || tblArray.Length <= 0) return null;

                var list = new List<格式表格>();

                foreach (var tbl in tblArray)
                {
                    list.Add(new 格式表格(new XWPFTable(tbl, this._文档)));
                }

                return list;
            }
        }

        public 格式文档管理器 插入二维文字表(string lines_txt, string fontFamilyName = "宋体", double fontSize = 11, bool fillBlankMode = false)
        {
            var lines = Utils.Text.FormatLineSplitter(lines_txt).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            return 插入二维文字表(lines, fontFamilyName, fontSize, fillBlankMode);
        }

        /// <summary>
        /// 按默认格式插入二维文字表。
        /// </summary>
        /// <param name="lines"></param>
        public 格式文档管理器 插入二维文字表(string[] lines, string fontFamilyName = "宋体", double fontSize = 11, bool fillBlankMode = false)
        {
            插入二维文字表(lines, this._文档, fontFamilyName, fontSize, fillBlankMode);
            return this;
        }

        internal static void 插入二维文字表(string[] lines, XWPFDocument m_Docx, string fontFamilyName = "宋体", double fontSize = 11, bool fillBlankMode = true)
        {
            var md = new MarkdownSharp.Markdown();
            var tableInfos = CustomMarkdownSupport.CompileTextTable(lines, ref md);

            for (int tIndex = 0; tIndex < tableInfos.Count; tIndex++)
            {
                var ti = tableInfos[tIndex];
                if (ti.TableLines.Count <= 0 || ti.ColumnAlignments.Count <= 0) continue;

                XWPFTable tableContent = m_Docx.CreateTable(ti.TableLines.Count - ti.ColumnDefinitionLinesCount - ti.CaptionSplitterLinesCount, ti.ColumnAlignments.Count);
                var tableArray = m_Docx.Document.body.GetTblArray();
                CT_Tbl m_CTTbl = tableArray[tableArray.Length - 1];  //获得文档中最新的表

                m_CTTbl.AddNewTblPr().jc = new CT_Jc();
                m_CTTbl.AddNewTblPr().jc.val = ST_Jc.center;//表在页面水平居中

                TableLine preTableLine = null;
                for (int li = 0; li < ti.TableLines.Count; li++)
                {
                    var tl = ti.TableLines[li];
                    if (preTableLine == null)
                    {
                        preTableLine = tl;
                    }
                    else
                    {
                        if (tl.Type == TableLineType.MergeLine)
                        {
                            for (int ci = 0; ci < Math.Min(preTableLine.Cells.Count, tl.Cells.Count); ci++)
                            {
                                preTableLine.Cells[ci] += tl.Cells[ci].Trim();
                            }
                        }
                        else if (tl.Type == TableLineType.Normal)
                        {
                            preTableLine = tl;
                        }
                    }  // 不考虑列定义行，统一居中。  
                }

                var cdLinesCount = 0;
                var captionSplittorCount = 0;
                var maxCols = 0;
                var fstRowCount = 0;

                List<string> colAlignDefinitionList = null;

                for (int li = 0; li < ti.TableLines.Count; li++)
                {
                    var tl = ti.TableLines[li];
                    if (li == 0)
                    {
                        fstRowCount = tl.Cells.Count;
                    }

                    if (tl.HeaderOrBodyType == HeaderOrBodyType.ColumnDifinition)
                    {
                        colAlignDefinitionList = new List<string>();
                        var pieces = tl.LineText.Split(new char[] { '|', '｜', }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var piece in pieces)
                        {
                            var tp = piece.Trim(new char[] { ' ', '　', '\t', });
                            if (tp.StartsWith(":") || tp.StartsWith("："))
                            {
                                if (tp.EndsWith(":") || tp.EndsWith("："))
                                {
                                    colAlignDefinitionList.Add("c");  // center
                                }
                                else
                                {
                                    colAlignDefinitionList.Add("l");  // left
                                }
                            }
                            else
                            {
                                if (tp.EndsWith(":") || tp.EndsWith("："))
                                {
                                    colAlignDefinitionList.Add("r");  // center
                                }
                                else
                                {
                                    colAlignDefinitionList.Add("l");  // left is default
                                }
                            }
                        }
                        cdLinesCount++;
                        continue;
                    }

                    if (tl.HeaderOrBodyType == HeaderOrBodyType.CaptionSplittorLine)
                    {
                        captionSplittorCount++;
                        continue;
                    }

                    if (tl.Type == TableLineType.Normal)  // 合并的行已经合并上去了，可以直接忽略了。
                    {
                        var row = tableContent.GetRow(li - cdLinesCount - captionSplittorCount);
                        for (int ci = 0; ci < tl.Cells.Count; ci++)
                        {
                            var align = GetAlign(ci, colAlignDefinitionList);
                            var cell = row.GetCell(ci);
                            XWPFParagraph para;
                            if (tl.HeaderOrBodyType == HeaderOrBodyType.HeaderLine)
                            {
                                para = QuestionBuilder.SetCellText(m_Docx, tableContent, tl.Cells[ci].Trim(),
                                    tl.HeaderOrBodyType == HeaderOrBodyType.HeaderLine, "c", fontFamilyName, fontSize, fillBlankMode);

                            }
                            else
                            {
                                para = QuestionBuilder.SetCellText(m_Docx, tableContent, tl.Cells[ci].Trim(),
                                    tl.HeaderOrBodyType == HeaderOrBodyType.HeaderLine, align, fontFamilyName, fontSize, fillBlankMode);
                            }
                            para.SpacingBefore = 40;
                            para.SpacingAfter = 40;
                            para.IndentFromLeft = 40;
                            para.IndentFromRight = 40;
                            cell.SetParagraph(para);
                            cell.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                            maxCols = Math.Max(maxCols, tl.Cells.Count);
                        }
                    }
                }

                // 首行合并
                if (fstRowCount == 1 && maxCols > 1)
                {
                    var fstrow = tableContent.GetRow(0);
                    fstrow.MergeCells(0, maxCols - 1);
                }
            }
        }

        internal static string GetAlign(int ci, List<string> colAlignDefinitionList)
        {
            if (colAlignDefinitionList == null) return "l";  // 默认 left

            if (ci < 0 || ci >= colAlignDefinitionList.Count) return "l";

            return colAlignDefinitionList[ci];
        }
    }

    public enum 页面类型
    {
        PageA4,
        Page6号信封,
        PageC5信封,
        Page9号信封,
        PageA3,
        Page8开,
        Page16开,
        Page大16开,
        Page32开,
        Page大32开,
        Page3号信封,
        PageDL信封,
        Page信纸,
        Page法律专用纸,
        PageExecutive,
        PageA5,
        PageB5JIS,
        Page10号信封,
        PageB5信封,
        PageMonarch信封,
        Page日式明信片,
        PageExecutiveJIS,
        Page16K,
    }

    public class 片段样式
    {
        public string 样式名 { get; set; } = "片段样式";

        public string 字体名 { get; set; } = "SimSun";

        public double 字号 { get; set; } = 12;  // 默认小四号字。

        public void 置中文字号(string fontsize)
        {
            switch (fontsize)
            {
                case "初号": { 字号 = 42; break; }
                case "小初": { 字号 = 36; break; }
                case "一号": { 字号 = 26; break; }
                case "小一": { 字号 = 24; break; }
                case "二号": { 字号 = 22; break; }
                case "小二": { 字号 = 18; break; }
                case "三号": { 字号 = 16; break; }
                case "小三": { 字号 = 15; break; }
                case "四号": { 字号 = 14; break; }
                case "小四": { 字号 = 12; break; }
                case "五号": { 字号 = 10.5; break; }
                case "小五": { 字号 = 9; break; }
                case "六号": { 字号 = 7.5; break; }
                case "小号": { 字号 = 6.5; break; }
                case "七号": { 字号 = 5.5; break; }
                case "八号": { 字号 = 5; break; }
                default: { throw new Exception("不能识别的中文字号！"); }
            }
        }

        public bool 加粗 { get; set; } = false;

        public bool 倾斜 { get; set; } = false;

        public string 色彩串 { get; set; } = "000000";

        public string 下划线 { get; set; } = "none";  // 不能识别的字符串均为“无下划线”。

        public bool 删除线 { get; set; } = false;

        /// <summary>
        /// 将常用中文字号名称转换为数值字号。
        /// </summary>
        /// <param name="cnfontsize">中文字号名。包括：初号、一到八号。其中七、八两号没有“小七”“小八”其余均有对应小号（例如“小初”“小二”等）。</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double 中文字号到数值(string cnfontsize)
        {
            switch (cnfontsize)
            {
                case "初号": return 42;
                case "小初": return 36;
                case "一号": return 26;
                case "小一": return 24;
                case "二号": return 22;
                case "小二": return 18;
                case "三号": return 16;
                case "小三": return 15;
                case "四号": return 14;
                case "小四": return 12;
                case "五号": return 10.5;
                case "小五": return 9;
                case "六号": return 7.5;
                case "小号": return 6.5;
                case "七号": return 5.5;
                case "八号": return 5;
                default: { throw new Exception("不能识别的中文字号！"); }
            }
        }

        public static double 中文到数值字号(string cnfontsize)
        {
            return 中文字号到数值(cnfontsize);
        }

        public static string 数值字号到中文(double fontsize)
        {
            if (fontsize == 42) return "初号";
            if (fontsize == 36) return "小初";
            if (fontsize == 26) return "一号";
            if (fontsize == 24) return "小一";
            if (fontsize == 22) return "二号";
            if (fontsize == 18) return "小二";
            if (fontsize == 16) return "三号";
            if (fontsize == 15) return "小三";
            if (fontsize == 14) return "四号";
            if (fontsize == 12) return "小四";
            if (fontsize == 10.5) return "五号";
            if (fontsize == 9) return "小五";
            if (fontsize == 7.5) return "六号";
            if (fontsize == 6.5) return "小号";
            if (fontsize == 5.5) return "七号";
            if (fontsize == 5) return "八号";

            return "未知字号";
        }

        public static string 数值到中文字号(double fontsize)
        {
            return 数值字号到中文(fontsize);
        }

        public override string ToString()
        {
            return $"\r\n；( {样式名}\r\n" +
                $"\r\n；字体名：{字体名}\r\n" +
                $"；字号：{字号}\r\n" +
                $"；中文字号：{数值到中文字号(字号)}\r\n" +
                $"；加粗：{加粗}\r\n" +
                $"；倾斜：{倾斜}\r\n" +
                $"；色彩串：{色彩串}\r\n" +
                $"；下划线：{下划线}\r\n" +
                $"；删除线：{删除线}\r\n" +
                $"\r\n；) {样式名}\r\n";
        }

        public string 导出片段样式表()
        {
            return ToString();
        }

        public bool 导入片段样式表(string styleText)
        {
            if (string.IsNullOrWhiteSpace(styleText)) return false;

            var dict = 纯文本处理器.取配置词典(styleText);
            var fontName = GetValueFromDict(dict, "字体名");
            字体名 = string.IsNullOrWhiteSpace(fontName) ? "宋体" : fontName;

            var fontSize = GetValueFromDict(dict, "字号");
            if (string.IsNullOrWhiteSpace(fontSize))
            {
                字号 = 12;  // 默认小四号字
            }
            else
            {
                if (double.TryParse(fontSize, out double fontSizeValue))
                {
                    字号 = fontSizeValue;
                }
                else
                {
                    字号 = 12;  // 默认小四号字
                }
            }

            // 中文字号由数值字号决定

            var bold = GetValueFromDict(dict, "加粗");
            if (string.IsNullOrWhiteSpace(bold))
            {
                加粗 = false;
            }
            else
            {
                if (bool.TryParse(bold, out bool boldValue))
                {
                    加粗 = boldValue;
                }
                else
                {
                    加粗 = false;
                }
            }

            var italic = GetValueFromDict(dict, "倾斜");
            if (string.IsNullOrWhiteSpace(italic))
            {
                倾斜 = false;
            }
            else
            {
                if (bool.TryParse(italic, out bool italicValue))
                {
                    倾斜 = italicValue;
                }
                else
                {
                    倾斜 = false;
                }
            }

            var color = GetValueFromDict(dict, "色彩串");
            色彩串 = string.IsNullOrWhiteSpace(color) ? "000000" : color;

            var underline = GetValueFromDict(dict, "下划线");
            下划线 = string.IsNullOrWhiteSpace(underline) ? "None" : underline;

            var strike = GetValueFromDict(dict, "删除线");
            if (string.IsNullOrWhiteSpace(strike))
            {
                删除线 = false;
            }
            else
            {
                if (bool.TryParse(strike, out bool strikeValue))
                {
                    删除线 = strikeValue;
                }
                else
                {
                    删除线 = false;
                }
            }

            return true;
        }

        protected string GetValueFromDict(Dictionary<string, string> dict, string key)
        {
            if (dict == null || string.IsNullOrWhiteSpace(key)) return null;

            if (dict.ContainsKey(key) == false) return null;

            return dict[key];
        }
    }

    public class 段落样式 : 片段样式
    {
        public 段落样式()
        {
            样式名 = "段落样式";
        }

        /// <summary>
        /// 这里的单位是半角字符数。
        /// </summary>
        public int 首行缩进 { get; set; } = 4;

        public string 对齐方式 { get; set; } = "both";

        public int 行间距磅值 { get; set; } = 25;

        /// <summary>
        /// 以磅（1/72 英寸）为单位。
        /// </summary>
        public int 段前磅值 { get; set; } = 0;

        /// <summary>
        /// 以磅（1/72 英寸）为单位。
        /// </summary>
        public int 段后磅值 { get; set; } = 0;

        public override string ToString()
        {
            return $"\r\n；( {样式名}\r\n\r\n" +
                $"；字体名：{字体名}\r\n" +
                $"；字号：{字号}\r\n" +
                $"；中文字号：{数值到中文字号(字号)}\r\n" +
                $"；加粗：{加粗}\r\n" +
                $"；倾斜：{倾斜}\r\n" +
                $"；色彩串：{色彩串}\r\n" +
                $"；下划线：{下划线}\r\n" +
                $"；删除线：{删除线}\r\n" +
                $"；首行缩进：{首行缩进}\r\n" +
                $"；对齐方式：{对齐方式}\r\n" +
                $"；行间距磅值：{行间距磅值}\r\n" +
                $"；段前磅值：{段前磅值}\r\n" +
                $"；段后磅值：{段后磅值}\r\n" +
                $"\r\n；) {样式名}\r\n";
        }

        public string 导出段落样式表()
        {
            return ToString();
        }

        public bool 导入段落样式表(string styleText)
        {
            if (string.IsNullOrWhiteSpace(styleText)) return false;

            var dict = 纯文本处理器.取配置词典(styleText);
            var fontName = GetValueFromDict(dict, "字体名");
            字体名 = string.IsNullOrWhiteSpace(fontName) ? "宋体" : fontName;

            var fontSize = GetValueFromDict(dict, "字号");
            if (string.IsNullOrWhiteSpace(fontSize))
            {
                字号 = 12;  // 默认小四号字
            }
            else
            {
                if (double.TryParse(fontSize, out double fontSizeValue))
                {
                    字号 = fontSizeValue;
                }
                else
                {
                    字号 = 12;  // 默认小四号字
                }
            }

            // 中文字号由数值字号决定

            var bold = GetValueFromDict(dict, "加粗");
            if (string.IsNullOrWhiteSpace(bold))
            {
                加粗 = false;
            }
            else
            {
                if (bool.TryParse(bold, out bool boldValue))
                {
                    加粗 = boldValue;
                }
                else
                {
                    加粗 = false;
                }
            }

            var italic = GetValueFromDict(dict, "倾斜");
            if (string.IsNullOrWhiteSpace(italic))
            {
                倾斜 = false;
            }
            else
            {
                if (bool.TryParse(italic, out bool italicValue))
                {
                    倾斜 = italicValue;
                }
                else
                {
                    倾斜 = false;
                }
            }

            var color = GetValueFromDict(dict, "色彩串");
            色彩串 = string.IsNullOrWhiteSpace(color) ? "000000" : color;    // 默认黑色

            var underline = GetValueFromDict(dict, "下划线");
            下划线 = string.IsNullOrWhiteSpace(underline) ? "none" : underline;    // 默认无下划线

            var strike = GetValueFromDict(dict, "删除线");
            if (string.IsNullOrWhiteSpace(strike))
            {
                删除线 = false;
            }
            else
            {
                if (bool.TryParse(strike, out bool strikeValue))
                {
                    删除线 = strikeValue;
                }
                else
                {
                    删除线 = false;
                }
            }

            //   $"；首行缩进
            var indent = GetValueFromDict(dict, "首行缩进");
            if (string.IsNullOrWhiteSpace(indent))
            {
                首行缩进 = 4;  // 默认两个全角字符
            }
            else
            {
                if (int.TryParse(indent, out int indentValue))
                {
                    首行缩进 = indentValue;
                }
                else
                {
                    首行缩进 = 4;  // 默认两个全角字符
                }
            }

            //   $"；对齐方式
            var align = GetValueFromDict(dict, "对齐方式");
            align = string.IsNullOrWhiteSpace(align) ? "both" : align;

            //   $"；行间距磅值
            var lineSpace = GetValueFromDict(dict, "行间距磅值");
            if (string.IsNullOrWhiteSpace(lineSpace))
            {
                行间距磅值 = 25;  // 默认每行固定值 25 磅
            }
            else
            {
                if (int.TryParse(lineSpace, out int lineSpaceValue))
                {
                    行间距磅值 = lineSpaceValue;
                }
                else
                {
                    行间距磅值 = 25;  // 默认每行固定值 25 磅
                }
            }

            //   $"；段前磅值
            var lineSpaceBefore = GetValueFromDict(dict, "段前磅值");
            if (string.IsNullOrWhiteSpace(lineSpaceBefore))
            {
                段前磅值 = 0;  // 默认段前 0 磅
            }
            else
            {
                if (int.TryParse(lineSpaceBefore, out int lineSpaceBeforeValue))
                {
                    段前磅值 = lineSpaceBeforeValue;
                }
                else
                {
                    段前磅值 = 0;  // 默认段前 0 磅
                }
            }

            //   $"；段后磅值
            var lineSpaceAfter = GetValueFromDict(dict, "段后磅值");
            if (string.IsNullOrWhiteSpace(lineSpaceAfter))
            {
                段后磅值 = 0;  // 默认段后 0 磅
            }
            else
            {
                if (int.TryParse(lineSpaceAfter, out int lineSpaceAfterValue))
                {
                    段后磅值 = lineSpaceAfterValue;
                }
                else
                {
                    段后磅值 = 0;  // 默认段后 0 磅
                }
            }

            return true;
        }
    }

    public class 格式表格
    {
        internal 格式表格(XWPFTable table)
        {
            this._表格体 = table;
            var tblLayout = table.GetCTTbl().tblPr.AddNewTblLayout();
            tblLayout.type = ST_TblLayoutType.@fixed;
        }

        private XWPFTable _表格体;

        public XWPFTable 表格体
        {
            get { return _表格体; }
        }

        public 格式表行 创建格式表行()
        {
            return new 格式表行(_表格体.CreateRow());
        }

        public 格式单元格 取格式单元格(int rowIndex, int columnIndex)
        {
            return new 格式单元格(_表格体.GetRow(rowIndex).GetCell(columnIndex));
        }

        public 格式表行 取格式表行(int rowIndex)
        {
            return new 格式表行(_表格体.GetRow(rowIndex));
        }

        /// <summary>
        /// 注意：为保证兼容性，没有修改。这个单元仍然是厘米。
        /// </summary>
        /// <param name="width"></param>
        public 格式表格 置宽度(double width)
        {
            var tbl = this._表格体.GetCTTbl();
            var tblPr = tbl.AddNewTblPr();
            tblPr.tblW.type = ST_TblWidth.dxa;   // 默认表格宽度格式类型是百分比，这里要改成 DXA（20个点，即10/72英寸）。
            tblPr.tblW.w = ((int)(width * 567)).ToString();
            return this;
        }

        public 格式表格 置厘米宽度(double width)
        {
            var tbl = this._表格体.GetCTTbl();
            var tblPr = tbl.AddNewTblPr();
            tblPr.tblW.type = ST_TblWidth.dxa;   // 默认表格宽度格式类型是百分比，这里要改成 DXA（20个点，即10/72英寸）。
            tblPr.tblW.w = ((int)(width * 567)).ToString();
            return this;
        }

        public 格式表格 置毫米宽度(double width)
        {
            var tbl = this._表格体.GetCTTbl();
            var tblPr = tbl.AddNewTblPr();
            tblPr.tblW.type = ST_TblWidth.dxa;   // 默认表格宽度格式类型是百分比，这里要改成 DXA（20个点，即10/72英寸）。
            tblPr.tblW.w = ((int)(width * 56.7)).ToString();
            return this;
        }

        public 格式表格 置磅宽度(int width)
        {
            var tbl = this._表格体.GetCTTbl();
            var tblPr = tbl.AddNewTblPr();
            tblPr.tblW.type = ST_TblWidth.dxa;   // 默认表格宽度格式类型是百分比，这里要改成 DXA（20个点，即10/72英寸）。
            tblPr.tblW.w = ((int)(width * 20)).ToString();
            return this;
        }

        public 格式表格 置缇宽度(int twips)
        {
            var tbl = this._表格体.GetCTTbl();
            var tblPr = tbl.AddNewTblPr();
            tblPr.tblW.type = ST_TblWidth.dxa;   // 默认表格宽度格式类型是百分比，这里要改成 DXA（20个点，即10/72英寸）。
            tblPr.tblW.w = twips.ToString();
            return this;
        }

        public 格式表格 置水平对齐(string align = "c")
        {
            if (string.IsNullOrEmpty(align)) align = "c";

            var align_txt = align.Trim().ToLower();

            var m_CTTbl = this._表格体.GetCTTbl();
            m_CTTbl.AddNewTblPr().jc = new CT_Jc();

            switch (align_txt)
            {
                case "l":
                case "left":
                case "左":
                case "居左":
                case "居左对齐":
                    {
                        m_CTTbl.AddNewTblPr().jc.val = ST_Jc.left;    //表在页面水平居左
                        break;
                    }
                case "r":
                case "right":
                case "右":
                case "居右":
                case "居右对齐":
                    {
                        m_CTTbl.AddNewTblPr().jc.val = ST_Jc.right;    //表在页面水平居右
                        break;
                    }
                case "b":
                case "both":
                case "两侧":
                case "两端":
                case "两侧对齐":
                case "两端对齐":
                    {
                        m_CTTbl.AddNewTblPr().jc.val = ST_Jc.both;    //表在页面水平两端对齐
                        break;
                    }
                case "c":
                case "center":
                case "中":
                case "居中":
                case "居中对齐":
                default:
                    {
                        m_CTTbl.AddNewTblPr().jc.val = ST_Jc.center;    //表在页面水平居中
                        break;
                    }
            }
            return this;
        }

        public 格式单元格 合并区域(int fromRow, int toRow, int fromCol, int toCol)
        {
            fromRow = Math.Max(0, fromRow);
            toRow = Math.Max(0, toRow);
            fromCol = Math.Max(0, fromCol);
            toCol = Math.Max(0, toCol);

            var minRow = Math.Min(fromRow, toRow);
            var maxRow = Math.Max(fromRow, toRow);
            var minCol = Math.Min(fromCol, toCol);
            var maxCol = Math.Max(fromCol, toCol);

            if (minRow == maxRow && minCol == maxCol) return null;   // 这种情况根本没有必要合并

            for (int rowIndex = minRow; rowIndex <= maxRow; rowIndex++)
            {
                if (minCol < maxCol)
                {
                    this._表格体.GetRow(rowIndex).MergeCells(minCol, maxCol);
                }

                var rowCell = this._表格体.GetRow(rowIndex).GetCell(minCol);
                var cttc = rowCell.GetCTTc();
                if (cttc.tcPr == null)
                {
                    cttc.AddNewTcPr();
                }

                if (rowIndex == minRow)
                {
                    // 第一个合并单元格被设置为 restart
                    rowCell.GetCTTc().tcPr.AddNewVMerge().val = ST_Merge.restart;
                }
                else
                {
                    // 从第二个开始，设置为 continue
                    rowCell.GetCTTc().tcPr.AddNewVMerge().val = ST_Merge.@continue;
                }
            }
            this._表格体.GetRow(minRow).GetCell(minCol).SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
            this._表格体.GetRow(minRow).GetCell(minCol).Paragraphs[0].Alignment = ParagraphAlignment.CENTER;
            return new 格式单元格(this._表格体.GetRow(minRow).GetCell(minCol));
        }

        public 格式表格 置格式表列宽(int colIndex, ulong twips)
        {
            this._表格体.SetColumnWidth(colIndex, twips);
            return this;
        }

        public 格式表格 置格式表缇列宽(int colIndex, ulong twips)
        {
            this._表格体.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };

            var tblGrid = this._表格体.GetCTTbl().tblGrid;
            var tblGridCol = tblGrid.gridCol;
            var existCols = tblGridCol.Count;

            if (existCols < colIndex + 1)
            {
                for (int i = existCols; i < colIndex + 1; i++)
                {
                    // tblGrid.AddNewGridCol();  // 重复，不需要！
                    tblGridCol.Add(new CT_TblGridCol());
                }
            }
            var col = tblGridCol[colIndex];
            col.w = twips;
            return this;
        }

        /// <summary>
        /// 1 缇 = 1/567 厘米。
        /// </summary>
        /// <param name="colIndex"></param>
        /// <param name="cm"></param>
        public 格式表格 置格式表厘米列宽(int colIndex, double cm)
        {
            var newWidth = ((ulong)(cm * 567));

            this._表格体.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };

            var tblGrid = this._表格体.GetCTTbl().tblGrid;
            var tblGridCol = tblGrid.gridCol;
            var existCols = tblGridCol.Count;

            if (existCols < colIndex + 1)
            {
                for (int i = existCols; i < colIndex + 1; i++)
                {
                    // tblGrid.AddNewGridCol();  // 重复，不需要！
                    tblGridCol.Add(new CT_TblGridCol());
                }
            }
            var col = tblGridCol[colIndex];
            col.w = newWidth;
            return this;
        }

        /// <summary>
        /// 1 缇 = 1/56.7 毫米。
        /// </summary>
        /// <param name="colIndex"></param>
        /// <param name="cm"></param>
        public 格式表格 置格式表毫米列宽(int colIndex, double mm)
        {
            var newWidth = ((ulong)(mm * 56.7));

            this._表格体.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };

            var tblGrid = this._表格体.GetCTTbl().tblGrid;
            var tblGridCol = tblGrid.gridCol;
            var existCols = tblGridCol.Count;

            if (existCols < colIndex + 1)
            {
                for (int i = existCols; i < colIndex + 1; i++)
                {
                    // tblGrid.AddNewGridCol();  // 重复，不需要！
                    tblGridCol.Add(new CT_TblGridCol());
                }
            }
            var col = tblGridCol[colIndex];
            col.w = newWidth;
            return this;
        }

        /// <summary>
        /// 1 缇 = 1/20 磅 = 1/1440 英寸 = 1/567 厘米。
        /// </summary>
        /// <param name="colIndex"></param>
        /// <param name="p"></param>
        public 格式表格 置格式表磅列宽(int colIndex, double p)
        {
            var newWidth = ((ulong)(p * 20));

            this._表格体.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };

            var tblGrid = this._表格体.GetCTTbl().tblGrid;
            var tblGridCol = tblGrid.gridCol;
            var existCols = tblGridCol.Count;

            if (existCols < colIndex + 1)
            {
                for (int i = existCols; i < colIndex + 1; i++)
                {
                    // tblGrid.AddNewGridCol();  // 重复，不需要！
                    tblGridCol.Add(new CT_TblGridCol());
                }
            }
            var col = tblGridCol[colIndex];
            col.w = newWidth;
            return this;
        }

        public 格式表格 置格式表行高(int rowIndex, int twips)
        {
            this._表格体.GetRow(rowIndex).Height = twips;
            return this;
        }

        public 格式表格 置格式表厘米行高(int rowIndex, double cm)
        {
            this._表格体.GetRow(rowIndex).Height = (int)(cm * 567);
            return this;
        }

        public 格式表格 置格式表毫米行高(int rowIndex, double mm)
        {
            this._表格体.GetRow(rowIndex).Height = (int)(mm * 567);
            return this;
        }

        public 格式表格 置格式表磅行高(int rowIndex, double p)
        {
            this._表格体.GetRow(rowIndex).Height = (int)(p * 20);  // 1 磅 = 20 缇
            return this;
        }

        public 格式表格 置格式表缇行高(int rowIndex, int twips)
        {
            this._表格体.GetRow(rowIndex).Height = twips;
            return this;
        }
    }

    public class 格式表行
    {
        internal 格式表行(XWPFTableRow row)
        {
            _表行体 = row;
        }

        private XWPFTableRow _表行体;

        public XWPFTableRow 表行体 { get { return _表行体; } }

        public 格式单元格 创建格式单元格()
        {
            return new 格式单元格(_表行体.CreateCell());
        }

        public 格式单元格 取格式单元格(int columnIndex)
        {
            return new 格式单元格(_表行体.GetCell(columnIndex));
        }

        /// <summary>
        /// 单位是缇（1/1440 英寸）。
        /// </summary>
        /// <param name="twips"></param>
        public 格式表行 置格式表行高(int twips)
        {
            _表行体.Height = twips;
            return this;
        }

        public 格式表行 置格式表缇行高(int twips)
        {
            _表行体.Height = twips;
            return this;
        }

        public 格式表行 置格式表厘米行高(double cm)
        {
            _表行体.Height = (int)(cm * 567);
            return this;
        }

        public 格式表行 置格式表毫米行高(double mm)
        {
            _表行体.Height = (int)(mm * 56.7);
            return this;
        }

        public 格式表行 置格式表磅行高(double p)
        {
            _表行体.Height = (int)(p * 20);
            return this;
        }
    }

    public class 格式单元格
    {
        internal 格式单元格(XWPFTableCell cell)
        {
            _单元格体 = cell;
        }

        private XWPFTableCell _单元格体;

        public XWPFTableCell 单元格体
        {
            get { return _单元格体; }
        }

        public void 插入文本(string text)
        {
            _单元格体.SetText(text);
        }

        public 格式单元格 置垂直对齐(string align = "c")
        {
            var align_txt = align.ToLower().Trim();

            switch (align_txt)
            {
                case "t":
                case "top":
                case "靠上":
                case "垂直靠上":
                case "居上":
                case "垂直居上":
                    {
                        _单元格体.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.TOP);
                        break;
                    }
                case "b":
                case "bottom":
                case "靠下":
                case "垂直靠下":
                case "居下":
                case "垂直居下":
                    {
                        _单元格体.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTTOM);
                        break;
                    }
                case "both":
                case "两侧":
                case "两端":
                case "垂直两侧":
                case "垂直两端":
                    {
                        _单元格体.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTH);
                        break;
                    }
                case "c":
                case "center":
                case "居中":
                case "垂直居中":
                default:
                    {
                        _单元格体.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                        break;
                    }
            }
            return this;
        }

        public 格式段落 插入段落()
        {
            var para = _单元格体.AddParagraph();
            return new 格式段落(para);
        }

        public 格式段落 取段落(int index)
        {
            if (this._单元格体.Paragraphs.Count < 0) return null;

            if (index < 0) index = 0;
            if (index >= this._单元格体.Paragraphs.Count) index = this._单元格体.Paragraphs.Count;

            return new 格式段落(this._单元格体.Paragraphs[index]);
        }

        public 格式段落 插入格式段落(string text, string fontFamilyName = "宋体",
            double fontSize = 14, bool isBold = true, bool isItalic = false, string underLineStyle = "", string rgbColor = "000000")
        {
            var newPara = _单元格体.AddParagraph();
            var newRun = newPara.CreateRun();
            newRun.SetText(text);
            newRun.FontFamily = fontFamilyName;
            newRun.FontSize = fontSize;
            newRun.IsBold = isBold;
            newRun.IsItalic = isItalic;
            var newRunSpan = new 格式片段(newRun);
            newRunSpan.置下划线(underLineStyle);
            newRunSpan.置色彩(rgbColor);

            return new 格式段落(newPara);
        }

        public 格式单元格 置左边框(格式边框类型 type, int size, int space, string rgbColor = "000000")
        {
            _单元格体.SetBorderLeft((XWPFTable.XWPFBorderType)(int)type, size, space, rgbColor);
            return this;
        }

        public 格式单元格 置上边框(格式边框类型 type, int size, int space, string rgbColor = "000000")
        {
            _单元格体.SetBorderTop((XWPFTable.XWPFBorderType)(int)type, size, space, rgbColor);
            return this;
        }

        public 格式单元格 置右边框(格式边框类型 type, int size, int space, string rgbColor = "000000")
        {
            _单元格体.SetBorderRight((XWPFTable.XWPFBorderType)(int)type, size, space, rgbColor);
            return this;
        }

        public 格式单元格 置下边框(格式边框类型 type, int size, int space, string rgbColor = "000000")
        {
            _单元格体.SetBorderBottom((XWPFTable.XWPFBorderType)(int)type, size, space, rgbColor);
            return this;
        }

        public 格式单元格 置内间距(double left, double top, double right, double bottom)
        {
            if (_单元格体.Paragraphs.Count <= 0) return this;

            _单元格体.Paragraphs[0].SpacingLineRule = LineSpacingRule.AUTO;
            _单元格体.Paragraphs[_单元格体.Paragraphs.Count - 1].SpacingLineRule = LineSpacingRule.AUTO;
            _单元格体.Paragraphs[0].SpacingBefore = (int)(top * 28.35 * 20);
            _单元格体.Paragraphs[_单元格体.Paragraphs.Count - 1].SpacingAfter = (int)(bottom * 28.35 * 20);  // 这个单位是 1/20 磅
            _单元格体.Paragraphs[0].IndentFromLeft = (int)(left * 567);
            _单元格体.Paragraphs[_单元格体.Paragraphs.Count - 1].IndentFromRight = (int)(right * 567);
            return this;
        }

        public 格式单元格 取消边框()
        {
            _单元格体.SetBorderLeft(XWPFTable.XWPFBorderType.NONE, 0, 2, "FFFFFF");
            _单元格体.SetBorderTop(XWPFTable.XWPFBorderType.NONE, 0, 2, "FFFFFF");
            _单元格体.SetBorderRight(XWPFTable.XWPFBorderType.NONE, 0, 2, "FFFFFF");
            _单元格体.SetBorderBottom(XWPFTable.XWPFBorderType.NONE, 0, 2, "FFFFFF");

            return this;
        }
    }

    public enum 格式边框类型
    {
        未设置 = XWPFTable.XWPFBorderType.NIL,
        无边框 = XWPFTable.XWPFBorderType.NONE,
        单线条边框 = XWPFTable.XWPFBorderType.SINGLE,
        厚线条边框 = XWPFTable.XWPFBorderType.THICK,
        双线边框 = XWPFTable.XWPFBorderType.DOUBLE,
        点线边框 = XWPFTable.XWPFBorderType.DOTTED,
        划线边框 = XWPFTable.XWPFBorderType.DASHED,
        点划线边框 = XWPFTable.XWPFBorderType.DOT_DASH,
    }

    public class 格式段落
    {
        internal 格式段落(XWPFParagraph paragraph)
        {
            this._段落体 = paragraph;
        }

        public static 片段样式 默认片段样式 { get; set; } = new 片段样式();

        private XWPFParagraph _段落体;

        public XWPFParagraph 段落体
        {
            get
            {
                return _段落体;
            }
            set { _段落体 = value; }
        }

        public 格式片段 创建片段()
        {
            return new 格式片段(this._段落体.CreateRun());
        }

        public 格式片段 按样式插入片段(string text, 片段样式 spanStyle)
        {
            if (string.IsNullOrEmpty(text))
                throw new Exception("“按样式插入片段”方法的第 1 参数不能为 空字符串 或 None。");

            if (spanStyle == null)
                spanStyle = 默认片段样式;

            var newrun = this._段落体.CreateRun();
            newrun.SetText(text);
            newrun.FontFamily = spanStyle.字体名;
            newrun.FontSize = spanStyle.字号;
            newrun.IsBold = spanStyle.加粗;
            newrun.IsItalic = spanStyle.倾斜;
            var newSpan = new 格式片段(newrun);
            newSpan.置下划线(spanStyle.下划线);
            newSpan.置色彩(spanStyle.色彩串);
            newSpan.置删除线(spanStyle.删除线);
            return newSpan;
        }

        public List<格式片段> 片段集
        {
            get
            {
                if (this._段落体.Runs == null || this._段落体.Runs.Count <= 0) return null;

                var list = new List<格式片段>();

                foreach (var run in _段落体.Runs)
                {
                    list.Add(new 格式片段(run));
                }

                return list;
            }
        }

        public 格式段落 置背景色(string color = "FFFFFF")
        {
            color = color.Trim(new char[] { ' ', '　', '\t', '#' });

            if (string.IsNullOrWhiteSpace(color))
            {
                color = "FFFFFF";
            }

            var regex = new Regex(@"^[0-9a-fA-F]{6,6}$");
            var match = regex.Match(color);
            if (match.Success == false)
                throw new Exception("【置背景色】方法参数不是有效的十六进制色彩值！");

            this._段落体.FillBackgroundColor = color;
            return this;
        }

        public 格式段落 置首行缩进(int unit)
        {
            this._段落体.IndentationFirstLine = unit;
            return this;
        }

        public 格式段落 置首行缩进字符数(int charNumber)
        {
            XWPFRun fstRun;
            if (_段落体.Runs.Count > 0)
            {
                fstRun = _段落体.Runs[0];
            }
            else
            {
                fstRun = _段落体.CreateRun();
            }

            if (fstRun.FontFamily == null || fstRun.FontSize < 0)
            {
                fstRun.SetFontFamily("simsun", FontCharRange.EastAsia);
                fstRun.FontSize = 10.5;
            }

            var fontStyle = System.Drawing.FontStyle.Regular;
            if (fstRun.IsBold) { fontStyle |= System.Drawing.FontStyle.Bold; }
            if (fstRun.IsItalic) { fontStyle |= System.Drawing.FontStyle.Italic; }

            this._段落体.IndentationFirstLine = GetIndentation(
                fstRun.FontFamily, (int)fstRun.FontSize, charNumber, fontStyle);
            return this;
        }

        /// <summary>
        /// 按字符数取段落缩进。
        /// </summary>
        /// <param name="fontname">文字类型名称</param>
        /// <param name="fontsize">文字大小</param>
        /// <param name="fontnum">缩进数目（字符数）</param>
        /// <param name="fontstyle">文字类型（斜体、粗体...）</param>
        /// <returns>对应的缩进距离</returns>
        private int GetIndentation(String fontname, int fontsize, int fontnum, System.Drawing.FontStyle fontstyle)
        {
            Graphics gp = new System.Windows.Forms.Control().CreateGraphics();
            gp.PageUnit = GraphicsUnit.Point;
            SizeF size = gp.MeasureString("字", new System.Drawing.Font(fontname, fontsize * 0.75F, fontstyle));
            return (int)size.Width * fontnum * 10;
        }

        public 格式段落 置对齐(string align)
        {
            switch (align.ToLower())
            {
                case "l":
                case "lt":
                case "lft":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        this._段落体.Alignment = ParagraphAlignment.LEFT; break;
                    }
                case "r":
                case "rt":
                case "rgt":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        this._段落体.Alignment = ParagraphAlignment.RIGHT; break;
                    }
                case "b":
                case "bth":
                case "both":
                case "两":
                case "两侧":
                case "两端":
                case "两端对齐":
                case "两侧对齐":
                    {
                        this._段落体.Alignment = ParagraphAlignment.BOTH; break;
                    }
                case "c":
                case "ct":
                case "cnt":
                case "center":
                case "中":
                case "居中":
                case "中对齐":
                case "居中对齐":
                    {
                        this._段落体.Alignment = ParagraphAlignment.CENTER; break;
                    }
                default:
                    {
                        this._段落体.Alignment = ParagraphAlignment.BOTH; break;
                    }
            }
            return this;
        }

        /// <summary>
        /// 这个是在当前段落内插入一个图标。
        /// </summary>
        /// <param name="imagePath"></param>
        public 格式段落 插入图像文件(string imagePath, double? custom_width = null, double? custom_height = null)
        {
            if (System.IO.File.Exists(imagePath))
            {
                var fi = new FileInfo(imagePath);
                int pictureType = -1;
                switch (fi.Extension.ToLower().Trim(new char[] { '.', ' ', '　', '\t' }))
                {
                    case "emf":
                        {
                            pictureType = 2; break;
                        }
                    case "wmf":
                        {
                            pictureType = 3; break;

                        }
                    case "pict":
                        {
                            pictureType = 4; break;
                        }
                    case "jpg":
                    case "jpeg":
                        {
                            pictureType = 5; break;
                        }
                    case "png":
                        {
                            pictureType = 6; break;
                        }
                    case "dib":
                        {
                            pictureType = 7; break;
                        }
                    case "gif":
                        {
                            pictureType = 8; break;
                        }
                    case "tif":
                    case "tiff":
                        {
                            pictureType = 9; break;
                        }
                    case "eps":
                        {
                            pictureType = 10; break;
                        }
                    case "bmp":
                        {
                            pictureType = 11; break;
                        }
                    case "wpg":
                        {
                            pictureType = 12; break;
                        }
                    case "svg":
                        {
                            pictureType = 13; break;
                        }
                    default:
                        {
                            throw new Exception("不能识别此图像文件格式！");
                        }
                }

                double width, height;
                using (var gfs1 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    if (custom_width == null && custom_height == null)
                    {
                        var img = System.Drawing.Image.FromStream(gfs1);
                        width = img.Width;
                        height = img.Height;
                        QuestionBuilder.ConvertImageSize(ref width, ref height);
                    }
                    else if (custom_height != null && custom_width != null)
                    {
                        width = custom_width.Value;
                        height = custom_height.Value;
                    }
                    else
                    {
                        var img = System.Drawing.Image.FromStream(gfs1);
                        width = (custom_width != null ? custom_width.Value : img.Width);
                        height = (custom_height != null ? custom_height.Value : img.Height);
                        QuestionBuilder.ConvertImageSize(ref width, ref height);
                    }
                }

                using (var gfs2 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {

                    _段落体.SetSpacingBetween(1, LineSpacingRule.AUTO);
                    var cr = _段落体.CreateRun();
                    cr.AddPicture(gfs2, pictureType, "img", (int)width, (int)height);  // 默认14cm，1cm = 360000 EMUS（English Metric Unit）;
                }
            }
            return this;
        }

        /// <summary>
        /// 这个是在当前段落内插入一个图标。
        /// </summary>
        /// <param name="imagePath"></param>
        public 格式段落 插入图像文件(string imagePath, int lineHeight)
        {
            if (System.IO.File.Exists(imagePath))
            {
                var fi = new FileInfo(imagePath);
                int pictureType = -1;
                switch (fi.Extension.ToLower().Trim(new char[] { '.', ' ', '　', '\t' }))
                {
                    case "emf":
                        {
                            pictureType = 2; break;
                        }
                    case "wmf":
                        {
                            pictureType = 3; break;

                        }
                    case "pict":
                        {
                            pictureType = 4; break;
                        }
                    case "jpg":
                    case "jpeg":
                        {
                            pictureType = 5; break;
                        }
                    case "png":
                        {
                            pictureType = 6; break;
                        }
                    case "dib":
                        {
                            pictureType = 7; break;
                        }
                    case "gif":
                        {
                            pictureType = 8; break;
                        }
                    case "tif":
                    case "tiff":
                        {
                            pictureType = 9; break;
                        }
                    case "eps":
                        {
                            pictureType = 10; break;
                        }
                    case "bmp":
                        {
                            pictureType = 11; break;
                        }
                    case "wpg":
                        {
                            pictureType = 12; break;
                        }
                    case "svg":
                        {
                            pictureType = 13; break;
                        }
                    default:
                        {
                            throw new Exception("不能识别此图像文件格式！");
                        }
                }

                double width, height;
                using (var gfs1 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    var img = System.Drawing.Image.FromStream(gfs1);
                    width = img.Width;
                    height = img.Height;
                    QuestionBuilder.ConvertImageSize(ref width, ref height);
                }

                width = width / (height / lineHeight);
                height = lineHeight;

                using (var gfs2 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    var cr = _段落体.CreateRun();
                    cr.AddPicture(gfs2, pictureType, "img", (int)width * 12700, (int)height * 12700);
                    // 1 磅是 1/72 英寸，1 英寸 = 914400 EMUS。914400/72 = 12700
                    // 默认14cm，1cm = 360000 EMUS（English Metric Unit）;
                }
            }
            return this;
        }

        public 格式段落 置行间距(double lineSpace, int lineSpacingRule = 1)
        {
            switch (lineSpacingRule)
            {
                case 3:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.ATLEAST);
                        break;
                    }
                case 2:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.EXACT);
                        break;
                    }
                case 1:
                default:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.AUTO);
                        break;
                    }
            }
            return this;
        }

        public 格式段落 置行间距(double lineSpace, 行间距类型 lineSpaceType)
        {
            switch (lineSpaceType)
            {
                case 行间距类型.最少行间距:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.ATLEAST);
                        break;
                    }
                case 行间距类型.精确行间距:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.EXACT);
                        break;
                    }
                case 行间距类型.自动行间距:
                default:
                    {
                        _段落体.SetSpacingBetween(lineSpace, LineSpacingRule.AUTO);
                        break;
                    }
            }
            return this;
        }

        public 格式段落 置倍数行间距(double times)
        {
            return 置行间距(times, 1);
        }

        public 格式段落 置毫米行间距(double mm)
        {
            return 置行间距(mm * 2.83527, 2);
        }

        public 格式段落 置厘米行间距(double cm)
        {
            return 置行间距(cm * 28.3527, 2);
        }

        public 格式段落 置磅行间距(int p)
        {
            return 置行间距(p, 2);
        }

        public 格式段落 置段前间距(int spacingBefore)
        {
            _段落体.SpacingBefore = Math.Max(0, spacingBefore);
            return this;
        }

        public 格式段落 置段前厘米间距(double cm)
        {
            return 置段前间距((int)(cm * 567));
        }

        public 格式段落 置段前毫米间距(double mm)
        {
            return 置段前间距((int)(mm * 56.7));
        }

        public 格式段落 置段前磅间距(int p)
        {
            _段落体.SpacingBefore = Math.Max(0, p * 20);
            return this;
        }

        /// <summary>
        /// 1 缇为 1/20 磅。
        /// </summary>
        /// <param name="p"></param>
        public 格式段落 置段前缇间距(int p)
        {
            _段落体.SpacingBefore = Math.Max(0, p);
            return this;
        }

        public 格式段落 置段后间距(int spacingBefore)
        {
            _段落体.SpacingAfter = Math.Max(0, spacingBefore);
            return this;
        }

        public 格式段落 置段后厘米间距(double cm)
        {
            return 置段后间距((int)(cm * 567));
        }

        public 格式段落 置段后毫米间距(double mm)
        {
            return 置段后间距((int)(mm * 56.7));
        }

        public 格式段落 置段后磅间距(int p)
        {
            _段落体.SpacingAfter = Math.Max(0, p * 20);
            return this;
        }

        /// <summary>
        /// 1 缇为 1/20 磅。
        /// </summary>
        /// <param name="p"></param>
        public 格式段落 置段后缇间距(int p)
        {
            _段落体.SpacingAfter = Math.Max(0, p);
            return this;
        }

        public 格式段落 置删除线(bool isStrikeThrough = true)
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置删除线(isStrikeThrough);
            }
            return this;
        }

        public 格式段落 置加粗(bool isBold = true)
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置加粗(isBold);
            }
            return this;
        }

        public 格式段落 置倾斜(bool isBold = true)
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置倾斜(isBold);
            }
            return this;
        }

        public 格式段落 置下划线(string underlineMark = "single")
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置下划线(underlineMark);
            }
            return this;
        }

        public 格式段落 置字体(string fontName = "宋体")
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置字体(fontName);
            }
            return this;
        }

        public 格式段落 置字体名(string fontName = "宋体")
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置字体(fontName);
            }
            return this;
        }

        public 格式段落 置字号(double fontSize = 11)
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置字号(fontSize);
            }
            return this;
        }


        public 格式段落 置色彩(string rgbString = "000000")
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置色彩(rgbString);
            }
            return this;
        }

        public 格式段落 置颜色(string rgbString = "000000")
        {
            var spans = this.片段集;
            if (spans == null || spans.Count <= 0) return this;

            foreach (var span in spans)
            {
                span.置色彩(rgbString);
            }
            return this;
        }
    }

    public enum 行间距类型
    {
        /// <summary>
        /// 按 12 磅的倍数设置。
        /// </summary>
        自动行间距 = LineSpacingRule.AUTO,
        /// <summary>
        /// 单位也是磅（1/72 英寸）。
        /// </summary>
        精确行间距 = LineSpacingRule.EXACT,
        /// <summary>
        /// 单位为磅（1/72 英寸）。
        /// </summary>
        最少行间距 = LineSpacingRule.ATLEAST,
    }

    public class 格式片段
    {
        internal 格式片段(XWPFRun run)
        {
            this._片段体 = run;
        }

        private XWPFRun _片段体;

        public XWPFRun 片段体
        {
            get { return _片段体; }
            set { _片段体 = value; }
        }

        public string 片段内文本
        {
            get
            {
                if (this._片段体 == null) return null;

                return this._片段体.Text;
            }
        }

        public 格式片段 置文本(string text)
        {
            _片段体.SetText(text);
            return this;
        }

        public 格式片段 置字体(string fontName)
        {
            _片段体.FontFamily = fontName;
            return this;
        }

        public 格式片段 置字体名(string fontName = "宋体")
        {
            _片段体.FontFamily = fontName;
            return this;
        }

        public 格式片段 置字号(double fontSize = 11)
        {
            _片段体.FontSize = fontSize;
            return this;
        }

        public 格式片段 置加粗(bool isBold = true)
        {
            _片段体.IsBold = isBold;
            return this;
        }

        public 格式片段 置倾斜(bool isItalic = true)
        {
            _片段体.IsItalic = isItalic;
            return this;
        }

        public 格式片段 置色彩(string rgbString = "000000")
        {
            _片段体.SetColor(rgbString);
            return this;
        }

        public 格式片段 置颜色(string rgbString = "000000")
        {
            _片段体.SetColor(rgbString);
            return this;
        }

        public 格式片段 置删除线(bool strike = true)
        {
            _片段体.IsStrikeThrough = strike;
            return this;
        }

        public 格式片段 置下划线(string underlineMark = "single")
        {
            if (string.IsNullOrWhiteSpace(underlineMark))
            {
                underlineMark = "None";
            }

            UnderlinePatterns underLine;

            switch (underlineMark.ToLower())
            {
                case "dash":
                case "划线":
                    {
                        underLine = UnderlinePatterns.Dash; break;
                    }
                case "dashdotdotheavy":
                case "重双点划线":
                    {
                        underLine = UnderlinePatterns.DashDotDotHeavy; break;
                    }
                case "dashdotheavy":
                case "重点划线":
                    {
                        underLine = UnderlinePatterns.DashDotHeavy; break;
                    }
                case "dashedheavy":
                case "重划线":
                    {
                        underLine = UnderlinePatterns.DashedHeavy; break;
                    }
                case "dashlong":
                case "长划线":
                    {
                        underLine = UnderlinePatterns.DashLong; break;
                    }
                case "dashlongheavy":
                case "重长划线":
                    {
                        underLine = UnderlinePatterns.DashLongHeavy; break;
                    }
                case "dotdash":
                case "点划线":
                    {
                        underLine = UnderlinePatterns.DotDash; break;
                    }
                case "dotdotdash":
                case "点点划线":
                    {
                        underLine = UnderlinePatterns.DotDotDash; break;
                    }
                case "single":
                case "单线":
                    {
                        underLine = UnderlinePatterns.Single; break;
                    }
                case "thick":
                case "厚线":
                    {
                        underLine = UnderlinePatterns.Thick; break;
                    }
                case "wave":
                case "波浪线":
                    {
                        underLine = UnderlinePatterns.Wave; break;
                    }
                case "wavedouble":
                case "wavydouble":
                case "双波浪线":
                    {
                        underLine = UnderlinePatterns.WavyDouble; break;
                    }
                case "waveheavy":
                case "wavyheavy":
                case "重波浪线":
                    {
                        underLine = UnderlinePatterns.WavyHeavy; break;
                    }
                case "words":  // 这个效果也是单线（与 Single 没什么区别）
                    {
                        underLine = UnderlinePatterns.Words; break;
                    }
                //case "none":
                default:
                    {
                        underLine = UnderlinePatterns.None; break;
                    }
            }

            _片段体.Underline = underLine;
            return this;
        }

        public 格式片段 追加文本(string text)
        {
            if (string.IsNullOrEmpty(text) == false)
            {
                _片段体.AppendText(text);
            }
            return this;
        }

        public 格式片段 插入文本(string text, int startIndex)
        {
            if (string.IsNullOrEmpty(text) == false)
            {
                _片段体.InsertText(text, startIndex);
            }
            return this;
        }

        public 格式片段 替换文本(string oldText, string newText)
        {
            if (string.IsNullOrEmpty(oldText) == false)
            {
                if (string.IsNullOrEmpty(newText))
                {
                    newText = "";
                }
                _片段体.ReplaceText(oldText, newText);
            }
            return this;
        }

        public 格式片段 插入图像文件(string imagePath)
        {
            if (System.IO.File.Exists(imagePath))
            {
                var fi = new FileInfo(imagePath);
                int pictureType = -1;
                switch (fi.Extension.ToLower().Trim(new char[] { '.', ' ', '　', '\t' }))
                {
                    case "emf":
                        {
                            pictureType = 2; break;
                        }
                    case "wmf":
                        {
                            pictureType = 3; break;

                        }
                    case "pict":
                        {
                            pictureType = 4; break;
                        }
                    case "jpg":
                    case "jpeg":
                        {
                            pictureType = 5; break;
                        }
                    case "png":
                        {
                            pictureType = 6; break;
                        }
                    case "dib":
                        {
                            pictureType = 7; break;
                        }
                    case "gif":
                        {
                            pictureType = 8; break;
                        }
                    case "tif":
                    case "tiff":
                        {
                            pictureType = 9; break;
                        }
                    case "eps":
                        {
                            pictureType = 10; break;
                        }
                    case "bmp":
                        {
                            pictureType = 11; break;
                        }
                    case "wpg":
                        {
                            pictureType = 12; break;
                        }
                    case "svg":
                        {
                            pictureType = 13; break;
                        }
                    default:
                        {
                            throw new Exception("不能识别此图像文件格式！");
                        }
                }

                double width, height;
                using (var gfs1 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    var img = System.Drawing.Image.FromStream(gfs1);
                    width = img.Width;
                    height = img.Height;
                    QuestionBuilder.ConvertImageSize(ref width, ref height);
                }

                var lineHeight = 11.0;
                if (_片段体.FontSize >= 10.5)
                {
                    lineHeight = this._片段体.FontSize * 0.8;
                }

                width = width / (height / lineHeight);
                height = lineHeight;

                using (var gfs2 = new System.IO.FileStream(imagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    this._片段体.AddPicture(gfs2, pictureType, "img", (int)width * 12700, (int)height * 12700);
                    // 1 磅是 1/72 英寸，1 英寸 = 914400 EMUS。914400/72 = 12700
                    // 默认14cm，1cm = 360000 EMUS（English Metric Unit）;
                }
            }
            return this;
        }
    }

    public static class 纯文本处理器
    {
        public static string 重复字符串(string originalString, int repeatCount)
        {
            if (string.IsNullOrEmpty(originalString)) return "";

            if (repeatCount < 0)
                throw new Exception("字符串重复次数不能小于 0。");

            // 使用 Enumerable.Repeat 和 string.Join 重复字符串
            return string.Join("", Enumerable.Repeat(originalString, repeatCount));
        }

        public static List<纯文本片段> 按正则分割(string regex, string source)
        {
            if (string.IsNullOrEmpty(regex)) return new List<纯文本片段>();
            if (string.IsNullOrEmpty(source)) return new List<纯文本片段>();

            var list = new List<纯文本片段>();
            try
            {
                var reg = new Regex(regex);
                var matches = reg.Matches(source);
                if (matches.Count <= 0)
                {
                    list.Add(new 纯文本片段()
                    {
                        开始索引 = 0,
                        结束索引 = source.Length,
                        是否匹配文本 = false,
                        源文本片段 = source,
                        替换文本片段 = source,
                    });
                    return list;
                }

                int newStartIndex = 0;
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    if (match.Index > 0)
                    {
                        var piece = source.Substring(newStartIndex, match.Index - newStartIndex);
                        list.Add(new 纯文本片段()
                        {
                            开始索引 = newStartIndex,
                            结束索引 = match.Index,
                            是否匹配文本 = false,
                            源文本片段 = piece,
                            替换文本片段 = piece,
                        });
                    }

                    list.Add(new 纯文本片段()
                    {
                        开始索引 = match.Index,
                        结束索引 = match.Index + match.Length,
                        是否匹配文本 = true,
                        源文本片段 = match.Value,
                    });
                    newStartIndex = match.Index + match.Length;
                }

                if (matches.Count > 0)
                {
                    var lastMatch = matches[matches.Count - 1];
                    if (lastMatch.Index < source.Length)
                    {
                        var nextIndex = lastMatch.Index + lastMatch.Length;
                        var lastPiece = source.Substring(nextIndex);
                        list.Add(new 纯文本片段()
                        {
                            开始索引 = nextIndex,
                            结束索引 = source.Length,
                            是否匹配文本 = false,
                            源文本片段 = lastPiece,
                            替换文本片段 = lastPiece,
                        });
                    }
                }

                return list;
            }
            catch
            {
                list.Clear();
                list.Add(new 纯文本片段()
                {
                    开始索引 = 0,
                    结束索引 = source.Length,
                    是否匹配文本 = false,
                    源文本片段 = source,
                    替换文本片段 = source,
                });
                return list;
            }
        }

        public static List<纯文本片段> 按正则分割(string regex, string source, bool muiltiLines, bool ignoreCase = false)
        {
            if (string.IsNullOrEmpty(regex)) return new List<纯文本片段>();
            if (string.IsNullOrEmpty(source)) return new List<纯文本片段>();

            var list = new List<纯文本片段>();
            try
            {

                var options = new RegexOptions();
                if (muiltiLines)
                {
                    options |= RegexOptions.Multiline;
                }

                if (ignoreCase)
                {
                    options |= RegexOptions.IgnoreCase;
                }

                var reg = new Regex(regex, options);

                var matches = reg.Matches(source);
                if (matches.Count <= 0)
                {
                    list.Add(new 纯文本片段()
                    {
                        开始索引 = 0,
                        结束索引 = source.Length,
                        是否匹配文本 = false,
                        源文本片段 = source,
                        替换文本片段 = source,
                    });
                    return list;
                }

                int newStartIndex = 0;
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    if (match.Index > 0)
                    {
                        var piece = source.Substring(newStartIndex, match.Index - newStartIndex);
                        list.Add(new 纯文本片段()
                        {
                            开始索引 = newStartIndex,
                            结束索引 = match.Index,
                            是否匹配文本 = false,
                            源文本片段 = piece,
                            替换文本片段 = piece,
                        });
                    }

                    list.Add(new 纯文本片段()
                    {
                        开始索引 = match.Index,
                        结束索引 = match.Index + match.Length,
                        是否匹配文本 = true,
                        源文本片段 = match.Value,
                    });
                    newStartIndex = match.Index + match.Length;
                }

                if (matches.Count > 0)
                {
                    var lastMatch = matches[matches.Count - 1];
                    if (lastMatch.Index < source.Length)
                    {
                        var nextIndex = lastMatch.Index + lastMatch.Length;
                        var lastPiece = source.Substring(nextIndex);
                        list.Add(new 纯文本片段()
                        {
                            开始索引 = nextIndex,
                            结束索引 = source.Length,
                            是否匹配文本 = false,
                            源文本片段 = lastPiece,
                            替换文本片段 = lastPiece,
                        });
                    }
                }

                return list;
            }
            catch
            {
                list.Clear();
                list.Add(new 纯文本片段()
                {
                    开始索引 = 0,
                    结束索引 = source.Length,
                    是否匹配文本 = false,
                    源文本片段 = source,
                    替换文本片段 = source,
                });
                return list;
            }
        }

        public static List<纯文本片段> 取匹配片段列表(string regex, string source, bool muiltiLines = true, bool ignoreCase = false)
        {
            if (string.IsNullOrEmpty(regex)) return new List<纯文本片段>();
            if (string.IsNullOrEmpty(source)) return new List<纯文本片段>();

            var list = new List<纯文本片段>();
            try
            {
                var options = new RegexOptions();
                if (muiltiLines)
                {
                    options |= RegexOptions.Multiline;
                }

                if (ignoreCase)
                {
                    options |= RegexOptions.IgnoreCase;
                }

                var reg = new Regex(regex, options);
                var matches = reg.Matches(source);
                if (matches.Count <= 0) return list;

                int newStartIndex = 0;
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    list.Add(new 纯文本片段()
                    {
                        开始索引 = match.Index,
                        结束索引 = match.Index + match.Length,
                        是否匹配文本 = true,
                        源文本片段 = match.Value,
                    });
                    newStartIndex = match.Index + match.Length;
                }

                return list;
            }
            catch
            {
                list.Clear();
                return list;
            }
        }

        public static List<纯文本片段> 匹配多次(string regex, string source, bool muiltiLines = true, bool ignoreCase = false)
        {
            return 取匹配片段列表(regex, source, muiltiLines, ignoreCase);
        }

        public static 纯文本片段 取匹配片段(string regex, string source, bool muiltiLines = true, bool ignoreCase = false)
        {
            if (string.IsNullOrEmpty(regex)) return null;
            if (string.IsNullOrEmpty(source)) return null;

            try
            {
                var options = new RegexOptions();
                if (muiltiLines)
                {
                    options |= RegexOptions.Multiline;
                }

                if (ignoreCase)
                {
                    options |= RegexOptions.IgnoreCase;
                }

                var reg = new Regex(regex, options);
                var match = reg.Match(source);
                if (match.Success == false) return null;

                return new 纯文本片段()
                {
                    开始索引 = match.Index,
                    结束索引 = match.Index + match.Length,
                    是否匹配文本 = true,
                    源文本片段 = match.Value,
                };
            }
            catch { return null; }
        }

        public static 纯文本片段 匹配单次(string regex, string source, bool muiltiLines = true, bool ignoreCase = false)
        {
            return 取匹配片段(regex, source, muiltiLines, ignoreCase);
        }

        public static string 取文本片段(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return Utils.Text.GetSpan(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static string 取片段(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return Utils.Text.GetSpan(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static string 取配置文本(string srcText, string header)
        {
            var head = $"[；;]\\[[ 　\t]{{0,}}{header.Trim()}[ 　\t]{{0,}}>{{0,}}";
            var tail = $"[；;]\\][ 　\t]{{0,}}{header.Trim()}";
            return Utils.Text.GetSpan(srcText, header, tail, true, 0, true, true);
        }

        public static 配置项 取配置项(string srcLine)
        {
            if (string.IsNullOrWhiteSpace(srcLine)) return null;

            var regItem = new Regex(@"(?<=(^[;；][ 　\t]{0,}))[一-龥A-Za-zａ-ｚＡ-Ｚ0-9０-９]{1,}(?=([ 　\t]{0,}[:：]))");
            var match = regItem.Match(srcLine);
            if (match.Success == false) return null;

            return new 配置项()
            {
                键 = match.Value.Trim(),
                值 = srcLine.Substring(match.Index + match.Length).Trim(new char[] { ' ', '　', '\t', ';', '；', ':', '：' })
            };
        }

        public static Tuple<string, string> 取配置元组(string srcLine)
        {
            配置项 config = 取配置项(srcLine);
            if (config == null) return null;

            return new Tuple<string, string>(config.键, config.值);
        }

        public static Dictionary<string, string> 取配置词典(string configLines)
        {
            if (string.IsNullOrWhiteSpace(configLines)) return null;

            var lines = configLines.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            if (lines.Length <= 0) return null;

            var dict = new Dictionary<string, string>();

            foreach (var line in lines)
            {
                var item = 取配置项(line);

                if (item == null) continue;

                dict.Add(item.键, item.值);
            }

            if (dict.Count > 0) return dict;

            return null;
        }

        public static Dictionary<string, string> 取配置字典(string configLines)
        {
            return 取配置词典(configLines);
        }

        public static Tuple<纯文本片段, 纯文本片段, 纯文本片段> 取文本片段信息(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return Utils.Text.GetSpanInfo(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static Tuple<纯文本片段, 纯文本片段, 纯文本片段> 取文本片段详情(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return 取文本片段信息(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static Tuple<纯文本片段, 纯文本片段, 纯文本片段> 取片段详情(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return 取文本片段信息(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static Tuple<纯文本片段, 纯文本片段, 纯文本片段> 取片段信息(string srcText, string header, string tail, bool byRegex = false,
             int startIndex = 0, bool ignoreCase = true, bool multiLine = true)
        {
            return 取文本片段信息(srcText, header, tail, byRegex, startIndex, ignoreCase, multiLine);
        }

        public static string 格式化行分割符(string text)
        {
            return Utils.Text.FormatLineSplitter(text);
        }

        /// <summary>
        /// 计算提供的文本宽度。全角算2，半角算1。
        /// </summary>
        /// <param name="text">要计算宽度的文本串。</param>
        /// <returns></returns>
        public static int 取文本宽度(string text)
        {
            return Utils.Text.GetTextWidth(text);
        }

        /// <summary>
        /// 计算提供的文本宽度。全角算2，半角算1。全角算2，半角算1。
        /// 这个只在在计算二维文字表中文本宽度时使用。列定义行的宽度总为0。
        /// </summary>
        /// <param name="text">二维文字表中的文本串。</param>
        /// <returns></returns>
        public static int 取文本宽度2(string text)
        {
            return Utils.Text.GetTextWidth2(text);
        }

        public static bool 是否图像链接行(string text)
        {
            return CustomMarkdownSupport.IsImageLinkLine(text);
        }

        public static bool 是否标题文本(string text)
        {
            var title = CustomMarkdownSupport.GetDocumentTitle(text);
            return string.IsNullOrEmpty(title) == false;
        }

        public static bool 是否Todo注释(string text)
        {
            return CustomMarkdownSupport.IsTodoCommentLine(text);
        }

        public static bool 是否二维文字表行(string text)
        {
            return CustomMarkdownSupport.IsTableRow(text);
        }

        public static bool 是否列对齐定义行(string text)
        {
            return CustomMarkdownSupport.IsColumnAlignmentDefinitionLine(text);
        }

        public static bool 是否表头分割行(string text)
        {
            return CustomMarkdownSupport.IsTableCaptionSplittor(text);
        }

        public static bool 是否文件链接行(string text)
        {
            return CustomMarkdownSupport.IsFileLinkLine(text);
        }

        public static bool 是否任务列表行(string text)
        {
            return CustomMarkdownSupport.IsTaskLine(text);
        }

        public static bool 是否废弃任务列表行(string text)
        {
            return CustomMarkdownSupport.IsAbortedTaskLine(text);
        }

        public static bool 是否分号注释行(string text)
        {
            return CustomMarkdownSupport.IsCommentLine(text);
        }

        public static bool 是否冒号注释行(string text)
        {
            return CustomMarkdownSupport.IsCompileCommentLine(text);
        }

        public static bool 是否日期标签文本(string text)
        {
            return CustomMarkdownSupport.IsDateLine(text);
        }

        public static string 格式化日期标签文本(string text)
        {
            return CustomMarkdownSupport.FormatDateLine(text);
        }

        public static string 取文档标题(string text)
        {
            return CustomMarkdownSupport.GetDocumentTitle(text);
        }

        public static string 取文档副标题(string text)
        {
            return CustomMarkdownSupport.GetSubTitle(text);
        }

        public static bool 是否页眉文本行(string text)
        {
            return CustomMarkdownSupport.IsPageHeader(text);
        }

        public static bool 是否页脚文本行(string text)
        {
            return CustomMarkdownSupport.IsPageFoot(text);
        }

        public static bool 是否空白字符串(string text)
        {
            return string.IsNullOrWhiteSpace(text);
        }

        public static bool 是否空白文本(string text)
        {
            return string.IsNullOrWhiteSpace(text);
        }

        public static bool 是否空字符串(string text)
        {
            return string.IsNullOrEmpty(text);
        }

        public static bool 是否空文本(string text)
        {
            return string.IsNullOrEmpty(text);
        }

        public static string 从图像链接取绝对路径(string markdownImageLink, string markdownFilePath)
        {
            return ImageLinkTool.GetRealPathFromImagelink(markdownImageLink, markdownFilePath);
        }

        /// <summary>
        /// 按正则表达式查找文本并替换。
        /// </summary>
        /// <param name="srcText">要在其中进行替换的源字符串。</param>
        /// <param name="partten">正则表达式字符串。</param>
        /// <param name="replacement">用于替换的字符串。</param>
        /// <returns></returns>
        public static string 按正则替换(string srcText, string pattern, string replacement)
        {
            return Regex.Replace(srcText, pattern, replacement);
        }

        public static string 弹性连接(string fst, string sec, bool ignoreCase = false)
        {
            if (string.IsNullOrWhiteSpace(fst)) return sec;
            if (string.IsNullOrWhiteSpace(sec)) return fst;

            for (int i = sec.Length - 1; i >= 0; i--)
            {
                var join_ignore_txt = sec.Substring(0, i);
                if (ignoreCase)
                {
                    if (fst.EndsWith(join_ignore_txt, StringComparison.CurrentCultureIgnoreCase))
                    {
                        return fst + sec.Substring(i);
                    }
                }
                else
                {
                    if (fst.EndsWith(join_ignore_txt))
                    {
                        return fst + sec.Substring(i);
                    }
                }
            }

            return fst + sec;
        }

        public static string 弹性连接(IronPython.Runtime.PythonList list, bool ignoreCase = false)
        {
            if (list == null) return null;
            if (list.Count <= 0) return "";

            var preTxt = "";
            foreach (var li in list)
            {
                preTxt = 弹性连接(preTxt, li as string, ignoreCase);
            }
            return preTxt;
        }

        public static string 全角转半角(string src)
        {
            return ChinesePinYin.FatAlphaAndNumbersToThin(src);
        }

        public static string 转为半角(string src)
        {
            return ChinesePinYin.FatAlphaAndNumbersToThin(src);
        }

        public static string 半角转全角(string src, bool onlyConvertPunctuation = false)
        {
            return ChinesePinYin.ThinAlphaAndNumbersToFat(src, onlyConvertPunctuation);
        }

        public static string 转为全角(string src, bool onlyConvertPunctuation = false)
        {
            return ChinesePinYin.ThinAlphaAndNumbersToFat(src, onlyConvertPunctuation);
        }

        public static string 取拼音首字母(string src)
        {
            return ChinesePinYin.ToChinesePinYinText(src);
        }

        public static string 格式化引号(string text, bool convertThinQuoters = false)
        {
            return Utils.Text.FormatQuoters(text, convertThinQuoters);
        }

        public static string 生成随机字符串(string chars, int minLength, int maxLength, int repeatTimes = 1, string splittor1 = "", string splittor2 = "\r\n")
        {
            if (maxLength < minLength)
            {
                var tmp = minLength;
                minLength = maxLength;
                maxLength = tmp;
            }

            var random = new System.Random();
            int length = random.Next(minLength, maxLength + 1);

            var sb = new StringBuilder();

            for (int i = 0; i < repeatTimes; i++)
            {
                char[] stringChars = new char[length];

                for (int j = 0; j < length; j++)
                {
                    stringChars[j] = chars[random.Next(chars.Length)];
                }

                // sb.Append(new String(stringChars));
                if (string.IsNullOrEmpty(splittor1))
                {
                    foreach (var c in stringChars)
                    {
                        sb.Append(c);
                    }
                }
                else
                {
                    if (stringChars.Length > 0)
                    {
                        for (int x = 0; x < stringChars.Length - 1; x++)
                        {
                            sb.Append(stringChars[x]);
                            sb.Append(splittor1);
                        }
                        sb.Append(stringChars[stringChars.Length - 1]);
                    }
                }

                if (i < repeatTimes - 1)
                {
                    sb.Append(splittor2);
                }
            }

            return sb.ToString();
        }

        public static IronPython.Runtime.PythonList 取随机字符串列表(IronPython.Runtime.PythonList list, int count)
        {
            if (list == null || list.Count <= 0 || count <= 0) return null;

            var resultList = new IronPython.Runtime.PythonList();

            if (list.Count == 1)
            {
                for (int i = 0; i < count; i++)
                {
                    resultList.Add(list[0]);
                }
                return resultList;
            }

            var random = new System.Random();
            for (int i = 0; i < count; i++)
            {
                var index = random.Next(0, list.Count - 1);
                resultList.Add(list[index]);
            }

            return resultList;
        }
        public static bool 是否半角标点字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[`~!@#$%\^&*()\-_\=\+\[\{\]\}\\\|;:'"",<.>/\?]+$");
        }

        public static bool 是否全角标点字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[．？！～｀＠＃＄％＾＆＊（）－＿＝＋［］｛｝＼／｜；：＇＂，＜。＞]+$");
        }

        public static bool 是否标点字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[`~!@#$%\^&*()\-_\=\+\[\{\]\}\\\|;:'"",<.>/\?．？！～｀＠＃＄％＾＆＊（）－＿＝＋［］｛｝＼／｜；：＇＂，＜。＞]+$");
        }

        public static bool 是否汉字字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[\u4e00-\u9fff]+$");
        }

        public static bool 是否半角英文字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[a-zA-Z]+$");
        }

        public static bool 是否全角英文字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[ａ-ｚＡ-Ｚ]+$");
        }

        public static bool 是否英文字符串(string chars)
        {
            return Regex.IsMatch(chars, @"^[a-zA-Zａ-ｚＡ-Ｚ]+$");
        }

        public static bool 是否半角阿拉伯数字(string chars)
        {
            return Regex.IsMatch(chars, @"^[0-9]+$");
        }

        public static bool 是否全角阿拉伯数字(string chars)
        {
            return Regex.IsMatch(chars, @"^[０-９]+$");
        }

        public static bool 是否阿位伯数字(string chars)
        {
            return Regex.IsMatch(chars, @"^[0-9０-９]+$");
        }

        public static bool 是否汉语拼音字符串(string chars, bool withNumbers = false)
        {
            if (withNumbers)
            {
                return Regex.IsMatch(chars, @"^[a-zA-Zａ-ｚＡ-Ｚ0-9０-９ 　\tāáǎàōóǒòêēéěèīíǐìūúǔùǖǘǚǜü]+$");
            }

            return Regex.IsMatch(chars, @"^[a-zA-Zａ-ｚＡ-Ｚ 　\tāáǎàōóǒòêēéěèīíǐìūúǔùǖǘǚǜü]+$");
        }


        /// <summary>
        /// 是否合法标识符（字母、数字或下划线字符_组成，且不能以数字开头），中文字符是否合法看第2参数。
        /// </summary>
        /// <param name="idTxt">待检验的标识符文本。</param>
        /// <param name="validateChinese">是否允许中文（一-龥）。</param>
        /// <returns>true | false。</returns>
        public static bool 是否合法标识符(string idTxt, bool validateChinese = false)
        {
            if (string.IsNullOrWhiteSpace(idTxt)) return false;
            Regex reg;

            if (validateChinese)
            {
                reg = new Regex(@"^[A-Za-z_一-龥][A-Za-z_0-9一-龥]*$");
            }
            else
            {
                reg = new Regex(@"^[A-Za-z_][A-Za-z_0-9]*$");
            }

            var match = reg.Match(idTxt);
            return match.Success;
        }
    }

    public class 纯文本片段
    {
        public int 开始索引 { get; set; }
        public int 结束索引 { get; set; }
        public int 长度 { get { return 结束索引 - 开始索引; } }
        public bool 是否匹配文本 { get; set; }
        public string 源文本片段 { get; set; }
        public string 替换文本片段 { get; set; } = null;
        public string 附加信息 { get; set; } = null;
        public string 类型信息 { get; set; } = null;
    }

    public class 匹配规则
    {
        public 匹配规则(string 头规则, string 尾规则, string 规则名称)
        {
            this._头规则 = 头规则;
            this._尾规则 = 尾规则;
            this._规则名称 = 规则名称;
        }

        private string _头规则;

        public string 头规则 { get => _头规则; }

        private string _尾规则;

        public string 尾规则 { get => _尾规则; }

        public string _规则名称;

        public string 规则名称 { get => _规则名称; }
    }

    public class 配置项
    {
        public string 键 { get; set; }
        public string 值 { get; set; }
    }

    #endregion

    #region Excel Help

    public class 工作簿管理器
    {
        public 工作簿管理器(bool autoCreateSheet = true)
        {
            _工作簿 = new XSSFWorkbook();

            置工作簿默认字体名("宋体");
            置工作簿默认字号(11);

            创建内置样式();

            if (autoCreateSheet)
                this.创建工作表("Sheet1");
        }

        public 工作簿管理器(string filePath)
        {
            using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                //把xls文件读入workbook变量里，之后就可以关闭了  
                if (filePath.ToLower().EndsWith(".xlsx"))
                {
                    _工作簿 = new XSSFWorkbook(fs);
                }
                else
                {
                    _工作簿 = new HSSFWorkbook(fs);
                }
                fs.Close();
            }

            置工作簿默认字体名("宋体");
            置工作簿默认字号(11);

            创建内置样式();
        }

        //public double 取列宽基准单位尺寸()
        //{
        //    string text = "0123456789";
        //    IFont font = _工作簿.GetFontAt(0);   //默认的字体
        //    Font newfont = new Font(font.FontName, (float)font.FontHeightInPoints, System.Drawing.FontStyle.Regular); // 设置字体和大小
        //    SizeF size = MeasureDisplayStringWidth(text, newfont);

        //    return size.Width / 10;
        //}

        //// 测量字符串在指定字体下的渲染尺寸
        //public static SizeF MeasureDisplayStringWidth(string text, Font font)
        //{
        //    using (Bitmap bitmap = new Bitmap(1, 1)) // 创建一个临时的Bitmap
        //    {
        //        using (Graphics graphics = Graphics.FromImage(bitmap))
        //        {
        //            // 设置测量选项，以便高度不影响宽度的测量
        //            StringFormat format = new StringFormat();
        //            format.LineAlignment = StringAlignment.Near;
        //            format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;

        //            // 测量字体渲染文本的宽度和高度
        //            SizeF size = graphics.MeasureString(text, font, PointF.Empty, format);
        //            return size;
        //        }
        //    }
        //}

        public 工作簿管理器 置工作簿默认字体名(string fontName = "宋体")
        {
            if (string.IsNullOrWhiteSpace(fontName))
                fontName = "宋体";

            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.FontName = fontName;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字号(double fontSize = 12)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.FontHeightInPoints = fontSize;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字体加粗(bool bold = true)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.IsBold = bold;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字体倾斜(bool italic = true)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.IsItalic = italic;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字体下划线类型(单元格下划线类型 underline = 单元格下划线类型.单下划线)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            switch (underline)
            {
                case 单元格下划线类型.无下划线:
                    font.Underline = FontUnderlineType.None;
                    break;
                case 单元格下划线类型.单下划线:
                    font.Underline = FontUnderlineType.Single;
                    break;
                case 单元格下划线类型.双下划线:
                    font.Underline = FontUnderlineType.Double;
                    break;
                case 单元格下划线类型.会计用单下划线:
                    font.Underline = FontUnderlineType.SingleAccounting;
                    break;
                case 单元格下划线类型.会计用双下划线:
                    font.Underline = FontUnderlineType.DoubleAccounting;
                    break;
                default:
                    font.Underline = FontUnderlineType.None;
                    break;
            }

            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字体删除线(bool strike = true)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.IsStrikeout = strike;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作簿管理器 置工作簿默认字体色彩标号(单元格色彩标号 color = 单元格色彩标号.红色)
        {
            IFont font = _工作簿.GetFontAt(0);   //默认的字体
            font.Color = (short)color;
            ((XSSFFont)font).SetFamily(NPOI.SS.UserModel.FontFamily.MODERN);
            ((XSSFFont)font).SetScheme(FontScheme.NONE);
            return this;
        }

        public 工作表 首工作表
        {
            get
            {
                var 工作表集 = 取所有工作表();
                if (工作表集 != null && 工作表集.Count > 0)
                {
                    工作表集[0].父工作簿 = this;
                    return 工作表集[0];
                }

                return null;
            }
        }

        public 工作表 尾工作表
        {
            get
            {
                var 工作表集 = 取所有工作表();
                if (工作表集 != null && 工作表集.Count > 0)
                {
                    工作表集[工作表集.Count - 1].父工作簿 = this;
                    return 工作表集[工作表集.Count - 1];
                }

                return null;
            }
        }

        public static 工作簿管理器 从文件创建(string filePath)
        {
            if (File.Exists(filePath) == false) return null;
            try
            {
                return new 工作簿管理器(filePath);
            }
            catch
            {
                return null;
            }
        }

        public 工作表 按位置取工作表(int index)
        {
            if (index < 0 || index >= _工作簿.NumberOfSheets) return null;

            return new 工作表(_工作簿.GetSheetAt(index)) { 父工作簿 = this, };
        }

        public 工作表 按名字取工作表(string name)
        {
            var sheet = _工作簿.GetSheet(name);
            if (sheet == null) return null;

            return new 工作表(sheet) { 父工作簿 = this, };
        }

        public 工作表 按名称取工作表(string name)
        {
            return 按名字取工作表(name);
        }

        public 工作簿管理器 删除工作表(int index)
        {
            _工作簿.RemoveSheetAt(index);
            return this;
        }

        public 工作簿管理器 删除工作表(string name)
        {
            var sheet = _工作簿.GetSheet(name);
            var index = _工作簿.GetSheetIndex(sheet);
            _工作簿.RemoveSheetAt(index);
            return this;
        }

        public List<工作表> 取所有工作表()
        {
            if (_工作簿.NumberOfSheets <= 0) return null;

            var list = new List<工作表>();
            for (int i = 0; i < _工作簿.NumberOfSheets; i++)
            {
                list.Add(new 工作表(_工作簿.GetSheetAt(i)) { 父工作簿 = this, });
            }
            return list;
        }

        public string[] 取所有工作表名称()
        {
            if (_工作簿.NumberOfSheets <= 0) return null;

            var sheetNames = new string[_工作簿.NumberOfSheets];
            for (int i = 0; i < _工作簿.NumberOfSheets; i++)
            {
                sheetNames[i] = _工作簿.GetSheetAt(i).SheetName;
            }
            return sheetNames;
        }

        public string[] 取所有工作表名字()
        {
            return 取所有工作表名称();
        }

        public 工作簿管理器 置工作表名称(工作表 sheet, string name)
        {
            this._工作簿.SetSheetName(this._工作簿.GetSheetIndex(sheet.工作表体), name);
            return this;
        }

        public 工作簿管理器 置工作表名称(int sheetIndex, string name)
        {
            this._工作簿.SetSheetName(sheetIndex, name);
            return this;
        }

        public 工作簿管理器 置工作表名称(ISheet sheet, string name)
        {
            this._工作簿.SetSheetName(this._工作簿.GetSheetIndex(sheet), name);
            return this;
        }

        public 工作表 激活工作表(string name)
        {
            var sht = this.按名字取工作表(name);
            if (sht == null) return null;

            this._工作簿.SetActiveSheet(this._工作簿.GetSheetIndex(sht.工作表体));

            return sht;
        }

        public 工作表 激活工作表(int index)
        {
            var sht = this.按位置取工作表(index);
            if (sht == null) return null;

            this._工作簿.SetActiveSheet(index);
            return sht;
        }

        public 工作表 激活工作表(工作表 sht)
        {
            if (sht == null) return null;

            this._工作簿.SetActiveSheet(this._工作簿.GetSheetIndex(sht.工作表体));
            return sht;
        }

        public int 工作表总数
        {
            get
            {
                return _工作簿.NumberOfSheets;
            }
        }


        public int 工作表数目
        {
            get
            {
                return _工作簿.NumberOfSheets;
            }
        }

        private IWorkbook _工作簿;

        public IWorkbook 工作簿 { get { return _工作簿; } }

        public 工作表 创建工作表(string sheetName)
        {
            return new 工作表(_工作簿.CreateSheet(sheetName)) { 父工作簿 = this, };
        }

        public 单元格样式 创建单元格样式(单元格字体 cellFont = null, string styleName = "")
        {
            var cellStyle = new 单元格样式(_工作簿.CreateCellStyle(), styleName);
            if (cellFont != null)
            {
                cellStyle.置单元格字体(cellFont);
            }
            return cellStyle;
        }

        public 单元格字体 创建单元格字体()
        {
            return new 单元格字体(_工作簿.CreateFont());
        }

        public 文件 保存(string filePath)
        {
            try
            {
                var fileInfo = new FileInfo(filePath);
                if (fileInfo.Directory.Exists == false)
                    fileInfo.Directory.Create();

                using (var sw = new FileStream(filePath, FileMode.Create))
                {
                    _工作簿.Write(sw);
                }
                return new 文件(filePath);
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning("保存失败！异常消息如下：\r\n" + ex.Message);
                return null;
            }
        }

        public 文件 保存工作簿(string filePath)
        {
            return 保存(filePath);
        }

        #region 几个内置的单元格字体和样式

        private void SetColorsOfCellStyle(单元格样式 cellStyle, 单元格色彩标号 foreColor, 单元格色彩标号 backColor)
        {
            cellStyle.置单元格前景色(foreColor);
            cellStyle.置单元格背景色(backColor);
        }

        private void SetColorsOfCellStyleList(List<单元格样式> list, 单元格色彩标号 foreColor, 单元格色彩标号 backColor)
        {
            if (list == null || list.Count <= 0) return;

            foreach (var item in list)
            {
                SetColorsOfCellStyle(item, foreColor, backColor);
            }
        }

        public void 置配色方案(配色方案 newSolution)
        {
            if (当前配色方案 != newSolution)
                当前配色方案 = newSolution;
        }

        public void 切换配色方案(配色方案 newSolution)
        {
            if (当前配色方案 != newSolution)
                当前配色方案 = newSolution;
        }

        private 配色方案 创建内置配色方案(string name, 单元格色彩标号 基本前景色, 单元格色彩标号 基本背景色,
                         单元格色彩标号 淡前景色, 单元格色彩标号 淡背景色,
                         单元格色彩标号 浅前景色, 单元格色彩标号 浅背景色,
                         单元格色彩标号 深前景色, 单元格色彩标号 深背景色)
        {

            #region 内置样式：主标题
            var s = new 配色方案(name, this);
            s.主标题单元格字体 = this.创建单元格字体();
            s.主标题单元格字体.置单元格字体名("宋体");
            s.主标题单元格字体.置单元格字号(20);
            s.主标题单元格字体.置单元格加粗(true);

            s.主标题单元格样式 = this.创建单元格样式(s.主标题单元格字体, "主标题样式");
            s.主标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.主标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.主标题单元格样式.置单元格前景色(基本前景色);
            s.主标题单元格样式.置单元格背景色(基本背景色);

            s.淡主标题单元格字体 = this.创建单元格字体();
            s.淡主标题单元格字体.置单元格字体名("宋体");
            s.淡主标题单元格字体.置单元格字号(20);
            s.淡主标题单元格字体.置单元格加粗(true);

            s.淡主标题单元格样式 = this.创建单元格样式(s.淡主标题单元格字体, "淡主标题单元格样式");
            s.淡主标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡主标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡主标题单元格样式.置单元格前景色(淡前景色);
            s.淡主标题单元格样式.置单元格背景色(淡背景色);

            s.浅主标题单元格字体 = this.创建单元格字体();
            s.浅主标题单元格字体.置单元格字体名("宋体");
            s.浅主标题单元格字体.置单元格字号(20);
            s.浅主标题单元格字体.置单元格加粗(true);

            s.浅主标题单元格样式 = this.创建单元格样式(s.浅主标题单元格字体, "浅主标题单元格样式");
            s.浅主标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅主标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅主标题单元格样式.置单元格前景色(浅前景色);
            s.浅主标题单元格样式.置单元格背景色(浅背景色);

            s.深主标题单元格字体 = this.创建单元格字体();
            s.深主标题单元格字体.置单元格字体名("宋体");
            s.深主标题单元格字体.置单元格字号(20);
            s.深主标题单元格字体.置单元格加粗(true);

            s.深主标题单元格样式 = this.创建单元格样式(s.深主标题单元格字体, "深主标题单元格样式");
            s.深主标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深主标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深主标题单元格样式.置单元格前景色(深前景色);
            s.深主标题单元格样式.置单元格背景色(深背景色);
            #endregion

            #region 内置样式：副标题
            s.副标题单元格字体 = this.创建单元格字体();
            s.副标题单元格字体.置单元格字体名("宋体");
            s.副标题单元格字体.置单元格字号(18);
            s.副标题单元格字体.置单元格加粗(true);

            s.副标题单元格样式 = this.创建单元格样式(s.副标题单元格字体, "副标题单元格样式");
            s.副标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.副标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.副标题单元格样式.置单元格前景色(基本前景色);
            s.副标题单元格样式.置单元格背景色(基本背景色);

            s.淡副标题单元格字体 = this.创建单元格字体();
            s.淡副标题单元格字体.置单元格字体名("宋体");
            s.淡副标题单元格字体.置单元格字号(18);
            s.淡副标题单元格字体.置单元格加粗(true);

            s.淡副标题单元格样式 = this.创建单元格样式(s.淡副标题单元格字体, "淡副标题单元格样式");
            s.淡副标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡副标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡副标题单元格样式.置单元格前景色(淡前景色);
            s.淡副标题单元格样式.置单元格背景色(淡背景色);

            s.浅副标题单元格字体 = this.创建单元格字体();
            s.浅副标题单元格字体.置单元格字体名("宋体");
            s.浅副标题单元格字体.置单元格字号(18);
            s.浅副标题单元格字体.置单元格加粗(true);

            s.浅副标题单元格样式 = this.创建单元格样式(s.浅副标题单元格字体, "浅副标题单元格样式");
            s.浅副标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅副标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅副标题单元格样式.置单元格前景色(浅前景色);
            s.浅副标题单元格样式.置单元格背景色(浅背景色);

            s.深副标题单元格字体 = this.创建单元格字体();
            s.深副标题单元格字体.置单元格字体名("宋体");
            s.深副标题单元格字体.置单元格字号(18);
            s.深副标题单元格字体.置单元格加粗(true);

            s.深副标题单元格样式 = this.创建单元格样式(s.深副标题单元格字体, "深副标题单元格样式");
            s.深副标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深副标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深副标题单元格样式.置单元格前景色(深前景色);
            s.深副标题单元格样式.置单元格背景色(深背景色);
            #endregion

            #region 内置样式：微标题
            s.微标题单元格字体 = this.创建单元格字体();
            s.微标题单元格字体.置单元格字体名("宋体");
            s.微标题单元格字体.置单元格字号(15);
            s.微标题单元格字体.置单元格加粗(true);

            s.微标题单元格样式 = this.创建单元格样式(s.微标题单元格字体, "微标题单元格样式");
            s.微标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.微标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.微标题单元格样式.置单元格前景色(基本前景色);
            s.微标题单元格样式.置单元格背景色(基本背景色);

            s.淡微标题单元格字体 = this.创建单元格字体();
            s.淡微标题单元格字体.置单元格字体名("宋体");
            s.淡微标题单元格字体.置单元格字号(15);
            s.淡微标题单元格字体.置单元格加粗(true);

            s.淡微标题单元格样式 = this.创建单元格样式(s.淡微标题单元格字体, "淡微标题单元格样式");
            s.淡微标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡微标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡微标题单元格样式.置单元格前景色(淡前景色);
            s.淡微标题单元格样式.置单元格背景色(淡背景色);

            s.浅微标题单元格字体 = this.创建单元格字体();
            s.浅微标题单元格字体.置单元格字体名("宋体");
            s.浅微标题单元格字体.置单元格字号(15);
            s.浅微标题单元格字体.置单元格加粗(true);

            s.浅微标题单元格样式 = this.创建单元格样式(s.浅微标题单元格字体, "浅微标题单元格样式");
            s.浅微标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅微标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅微标题单元格样式.置单元格前景色(浅前景色);
            s.浅微标题单元格样式.置单元格背景色(浅背景色);

            s.深微标题单元格字体 = this.创建单元格字体();
            s.深微标题单元格字体.置单元格字体名("宋体");
            s.深微标题单元格字体.置单元格字号(15);
            s.深微标题单元格字体.置单元格加粗(true);

            s.深微标题单元格样式 = this.创建单元格样式(s.深微标题单元格字体, "深微标题单元格样式");
            s.深微标题单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深微标题单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深微标题单元格样式.置单元格前景色(深前景色);
            s.深微标题单元格样式.置单元格背景色(深背景色);
            #endregion

            #region 内置样式：较窄单元格样式
            s.较窄单元格字体 = this.创建单元格字体();
            s.较窄单元格字体.置单元格字体名("宋体");
            s.较窄单元格字体.置单元格字号(12);
            s.较窄单元格字体.置单元格加粗(false);

            s.较窄单元格样式 = this.创建单元格样式(s.较窄单元格字体, "较窄单元格样式");
            s.较窄单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.较窄单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.较窄单元格样式.置单元格前景色(基本前景色);
            s.较窄单元格样式.置单元格背景色(基本背景色);
            s.较窄单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.较窄单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.较窄单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.较窄单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.淡较窄单元格字体 = this.创建单元格字体();
            s.淡较窄单元格字体.置单元格字体名("宋体");
            s.淡较窄单元格字体.置单元格字号(12);
            s.淡较窄单元格字体.置单元格加粗(false);

            s.淡较窄单元格样式 = this.创建单元格样式(s.淡较窄单元格字体, "淡较窄单元格样式");
            s.淡较窄单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡较窄单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡较窄单元格样式.置单元格前景色(淡前景色);
            s.淡较窄单元格样式.置单元格背景色(淡背景色);
            s.淡较窄单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.淡较窄单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.淡较窄单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.淡较窄单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.浅较窄单元格字体 = this.创建单元格字体();
            s.浅较窄单元格字体.置单元格字体名("宋体");
            s.浅较窄单元格字体.置单元格字号(12);
            s.浅较窄单元格字体.置单元格加粗(false);

            s.浅较窄单元格样式 = this.创建单元格样式(s.浅较窄单元格字体, "浅较窄单元格样式");
            s.浅较窄单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅较窄单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅较窄单元格样式.置单元格前景色(浅前景色);
            s.浅较窄单元格样式.置单元格背景色(浅背景色);
            s.浅较窄单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.浅较窄单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.浅较窄单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.浅较窄单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.深较窄单元格字体 = this.创建单元格字体();
            s.深较窄单元格字体.置单元格字体名("宋体");
            s.深较窄单元格字体.置单元格字号(12);
            s.深较窄单元格字体.置单元格加粗(false);

            s.深较窄单元格样式 = this.创建单元格样式(s.深较窄单元格字体, "深较窄单元格样式");
            s.深较窄单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深较窄单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深较窄单元格样式.置单元格前景色(深前景色);
            s.深较窄单元格样式.置单元格背景色(深背景色);
            s.深较窄单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.深较窄单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.深较窄单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.深较窄单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            #endregion

            #region 内置样式：较宽单元格样式
            s.较宽单元格字体 = this.创建单元格字体();
            s.较宽单元格字体.置单元格字体名("宋体");
            s.较宽单元格字体.置单元格字号(12);
            s.较宽单元格字体.置单元格加粗(false);

            s.较宽单元格样式 = this.创建单元格样式(s.较宽单元格字体, "较宽单元格样式");
            s.较宽单元格样式.置水平对齐(单元格水平对齐.水平居左);
            s.较宽单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.较宽单元格样式.置单元格前景色(基本前景色);
            s.较宽单元格样式.置单元格背景色(基本背景色);
            s.较宽单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.较宽单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.较宽单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.较宽单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            s.较宽单元格样式.置自动换行(true);

            s.淡较宽单元格字体 = this.创建单元格字体();
            s.淡较宽单元格字体.置单元格字体名("宋体");
            s.淡较宽单元格字体.置单元格字号(12);
            s.淡较宽单元格字体.置单元格加粗(false);

            s.淡较宽单元格样式 = this.创建单元格样式(s.淡较宽单元格字体, "淡较宽单元格样式");
            s.淡较宽单元格样式.置水平对齐(单元格水平对齐.水平居左);
            s.淡较宽单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡较宽单元格样式.置单元格前景色(淡前景色);
            s.淡较宽单元格样式.置单元格背景色(淡背景色);
            s.淡较宽单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.淡较宽单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.淡较宽单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.淡较宽单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            s.淡较宽单元格样式.置自动换行(true);

            s.浅较宽单元格字体 = this.创建单元格字体();
            s.浅较宽单元格字体.置单元格字体名("宋体");
            s.浅较宽单元格字体.置单元格字号(12);
            s.浅较宽单元格字体.置单元格加粗(false);

            s.浅较宽单元格样式 = this.创建单元格样式(s.浅较宽单元格字体, "浅较宽单元格样式");
            s.浅较宽单元格样式.置水平对齐(单元格水平对齐.水平居左);
            s.浅较宽单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅较宽单元格样式.置单元格前景色(浅前景色);
            s.浅较宽单元格样式.置单元格背景色(浅背景色);
            s.浅较宽单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.浅较宽单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.浅较宽单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.浅较宽单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            s.浅较宽单元格样式.置自动换行(true);

            s.深较宽单元格字体 = this.创建单元格字体();
            s.深较宽单元格字体.置单元格字体名("宋体");
            s.深较宽单元格字体.置单元格字号(12);
            s.深较宽单元格字体.置单元格加粗(false);

            s.深较宽单元格样式 = this.创建单元格样式(s.深较宽单元格字体, "深较宽单元格样式");
            s.深较宽单元格样式.置水平对齐(单元格水平对齐.水平居左);
            s.深较宽单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深较宽单元格样式.置单元格前景色(深前景色);
            s.深较宽单元格样式.置单元格背景色(深背景色);
            s.深较宽单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.深较宽单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.深较宽单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.深较宽单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            s.深较宽单元格样式.置自动换行(true);
            #endregion

            #region 内置样式：默认单元格样式
            s.默认单元格字体 = this.创建单元格字体();
            s.默认单元格字体.置单元格字体名("宋体");
            s.默认单元格字体.置单元格字号(11);
            s.默认单元格字体.置单元格加粗(false);

            s.默认单元格样式 = this.创建单元格样式(s.默认单元格字体, "默认单元格样式");
            s.默认单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.默认单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.默认单元格样式.置单元格前景色(基本前景色);
            s.默认单元格样式.置单元格背景色(基本背景色);
            s.默认单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.默认单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.默认单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.默认单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.淡默认单元格字体 = this.创建单元格字体();
            s.淡默认单元格字体.置单元格字体名("宋体");
            s.淡默认单元格字体.置单元格字号(11);
            s.淡默认单元格字体.置单元格加粗(false);

            s.淡默认单元格样式 = this.创建单元格样式(s.淡默认单元格字体, "淡默认单元格样式");
            s.淡默认单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡默认单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡默认单元格样式.置单元格前景色(淡前景色);
            s.淡默认单元格样式.置单元格背景色(淡背景色);
            s.淡默认单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.淡默认单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.淡默认单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.淡默认单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.浅默认单元格字体 = this.创建单元格字体();
            s.浅默认单元格字体.置单元格字体名("宋体");
            s.浅默认单元格字体.置单元格字号(11);
            s.浅默认单元格字体.置单元格加粗(false);

            s.浅默认单元格样式 = this.创建单元格样式(s.浅默认单元格字体, "浅默认单元格样式");
            s.浅默认单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅默认单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅默认单元格样式.置单元格前景色(浅前景色);
            s.浅默认单元格样式.置单元格背景色(浅背景色);
            s.浅默认单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.浅默认单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.浅默认单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.浅默认单元格样式.置单元格下边框类型(单元格边框类型.细边框);

            s.深默认单元格字体 = this.创建单元格字体();
            s.深默认单元格字体.置单元格字体名("宋体");
            s.深默认单元格字体.置单元格字号(11);
            s.深默认单元格字体.置单元格加粗(false);

            s.深默认单元格样式 = this.创建单元格样式(s.深默认单元格字体, "深默认单元格样式");
            s.深默认单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深默认单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深默认单元格样式.置单元格前景色(深前景色);
            s.深默认单元格样式.置单元格背景色(深背景色);
            s.深默认单元格样式.置单元格左边框类型(单元格边框类型.细边框);
            s.深默认单元格样式.置单元格右边框类型(单元格边框类型.细边框);
            s.深默认单元格样式.置单元格上边框类型(单元格边框类型.细边框);
            s.深默认单元格样式.置单元格下边框类型(单元格边框类型.细边框);
            #endregion

            #region 内置样式：无框单元格样式
            s.无框单元格字体 = this.创建单元格字体();
            s.无框单元格字体.置单元格字体名("宋体");
            s.无框单元格字体.置单元格字号(11);
            s.无框单元格字体.置单元格加粗(false);

            s.无框单元格样式 = this.创建单元格样式(s.默认单元格字体, "无框单元格样式");
            s.无框单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.无框单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.无框单元格样式.置单元格前景色(基本前景色);
            s.无框单元格样式.置单元格背景色(基本背景色);
            s.无框单元格样式.置单元格左边框类型(单元格边框类型.无边框);
            s.无框单元格样式.置单元格右边框类型(单元格边框类型.无边框);
            s.无框单元格样式.置单元格上边框类型(单元格边框类型.无边框);
            s.无框单元格样式.置单元格下边框类型(单元格边框类型.无边框);

            s.淡无框单元格字体 = this.创建单元格字体();
            s.淡无框单元格字体.置单元格字体名("宋体");
            s.淡无框单元格字体.置单元格字号(11);
            s.淡无框单元格字体.置单元格加粗(false);

            s.淡无框单元格样式 = this.创建单元格样式(s.淡默认单元格字体, "淡无框单元格样式");
            s.淡无框单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.淡无框单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.淡无框单元格样式.置单元格前景色(淡前景色);
            s.淡无框单元格样式.置单元格背景色(淡背景色);
            s.淡无框单元格样式.置单元格左边框类型(单元格边框类型.无边框);
            s.淡无框单元格样式.置单元格右边框类型(单元格边框类型.无边框);
            s.淡无框单元格样式.置单元格上边框类型(单元格边框类型.无边框);
            s.淡无框单元格样式.置单元格下边框类型(单元格边框类型.无边框);

            s.浅无框单元格字体 = this.创建单元格字体();
            s.浅无框单元格字体.置单元格字体名("宋体");
            s.浅无框单元格字体.置单元格字号(11);
            s.浅无框单元格字体.置单元格加粗(false);

            s.浅无框单元格样式 = this.创建单元格样式(s.浅默认单元格字体, "浅无框单元格样式");
            s.浅无框单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.浅无框单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.浅无框单元格样式.置单元格前景色(浅前景色);
            s.浅无框单元格样式.置单元格背景色(浅背景色);
            s.浅无框单元格样式.置单元格左边框类型(单元格边框类型.无边框);
            s.浅无框单元格样式.置单元格右边框类型(单元格边框类型.无边框);
            s.浅无框单元格样式.置单元格上边框类型(单元格边框类型.无边框);
            s.浅无框单元格样式.置单元格下边框类型(单元格边框类型.无边框);

            s.深无框单元格字体 = this.创建单元格字体();
            s.深无框单元格字体.置单元格字体名("宋体");
            s.深无框单元格字体.置单元格字号(11);
            s.深无框单元格字体.置单元格加粗(false);

            s.深无框单元格样式 = this.创建单元格样式(s.深默认单元格字体, "深无框单元格样式");
            s.深无框单元格样式.置水平对齐(单元格水平对齐.水平居中);
            s.深无框单元格样式.置垂直对齐(单元格垂直对齐.垂直居中);
            s.深无框单元格样式.置单元格前景色(深前景色);
            s.深无框单元格样式.置单元格背景色(深背景色);
            s.深无框单元格样式.置单元格左边框类型(单元格边框类型.无边框);
            s.深无框单元格样式.置单元格右边框类型(单元格边框类型.无边框);
            s.深无框单元格样式.置单元格上边框类型(单元格边框类型.无边框);
            s.深无框单元格样式.置单元格下边框类型(单元格边框类型.无边框);
            #endregion

            return s;
        }

        /// <summary>
        /// 默认为白色系。
        /// </summary>
        private void 创建内置样式()
        {
            // 初始只创建默认的白色系，其它需要的时候才会创建。
            当前配色方案 = 白色方案;  // 注意这里不用字段，都用属性！
        }

        private 配色方案 _白色方案 = null;
        public 配色方案 白色方案
        {
            get
            {
                if (_白色方案 == null)
                {
                    _白色方案 = 创建内置配色方案("白色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.二十五灰色,
                        单元格色彩标号.白色, 单元格色彩标号.五十灰色,
                        单元格色彩标号.白色, 单元格色彩标号.八十灰色);
                }
                return _白色方案;
            }
        }

        private 配色方案 _黑色方案 = null;
        public 配色方案 黑色方案
        {
            get
            {
                if (_黑色方案 == null)
                {
                    _黑色方案 = 创建内置配色方案("黑色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.二十五灰色,
                        单元格色彩标号.白色, 单元格色彩标号.五十灰色,
                        单元格色彩标号.白色, 单元格色彩标号.黑色);
                }
                return _黑色方案;
            }
        }

        private 配色方案 _红色方案 = null;
        public 配色方案 红色方案
        {
            get
            {
                if (_红色方案 == null)
                {
                    _红色方案 = 创建内置配色方案("红色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.玫瑰,
                        单元格色彩标号.白色, 单元格色彩标号.红色,
                        单元格色彩标号.白色, 单元格色彩标号.深红色);
                }
                return _红色方案;
            }
        }

        private 配色方案 _橙色方案 = null;
        public 配色方案 橙色方案
        {
            get
            {
                if (_橙色方案 == null)
                {
                    _橙色方案 = 创建内置配色方案("橙色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.棕褐色,
                        单元格色彩标号.黑色, 单元格色彩标号.浅橙色,
                        单元格色彩标号.白色, 单元格色彩标号.橙色);
                }
                return _橙色方案;
            }
        }

        private 配色方案 _黄色方案 = null;
        public 配色方案 黄色方案
        {
            get
            {
                if (_黄色方案 == null)
                {
                    _黄色方案 = 创建内置配色方案("黄色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.浅黄色,
                        单元格色彩标号.黑色, 单元格色彩标号.黄色,
                        单元格色彩标号.黑色, 单元格色彩标号.金色);
                }
                return _黄色方案;
            }
        }

        private 配色方案 _棕色方案 = null;
        public 配色方案 棕色方案
        {
            get
            {
                if (_棕色方案 == null)
                {
                    _棕色方案 = 创建内置配色方案("棕色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.棕褐色,
                        单元格色彩标号.黑色, 单元格色彩标号.珊瑚色,
                        单元格色彩标号.白色, 单元格色彩标号.棕色);
                }
                return _棕色方案;
            }
        }

        private 配色方案 _绿色方案 = null;
        public 配色方案 绿色方案
        {
            get
            {
                if (_绿色方案 == null)
                {
                    _绿色方案 = 创建内置配色方案("绿色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.浅绿色,
                        单元格色彩标号.白色, 单元格色彩标号.绿色,
                        单元格色彩标号.白色, 单元格色彩标号.深绿色);
                }
                return _绿色方案;
            }
        }

        private 配色方案 _青色方案 = null;
        public 配色方案 青色方案
        {
            get
            {
                if (_青色方案 == null)
                {
                    _青色方案 = 创建内置配色方案("青色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.浅绿松石,
                        单元格色彩标号.白色, 单元格色彩标号.青色,
                        单元格色彩标号.白色, 单元格色彩标号.深青色);
                }
                return _青色方案;
            }
        }

        private 配色方案 _蓝色方案 = null;
        public 配色方案 蓝色方案
        {
            get
            {
                if (_蓝色方案 == null)
                {
                    _蓝色方案 = 创建内置配色方案("蓝色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.淡蓝色,
                        单元格色彩标号.白色, 单元格色彩标号.浅蓝色,
                        单元格色彩标号.白色, 单元格色彩标号.深蓝色);
                }
                return _蓝色方案;
            }
        }

        private 配色方案 _紫色方案 = null;
        public 配色方案 紫色方案
        {
            get
            {
                if (_紫色方案 == null)
                {
                    _紫色方案 = 创建内置配色方案("紫色方案", 单元格色彩标号.黑色, 单元格色彩标号.白色,
                        单元格色彩标号.黑色, 单元格色彩标号.薰衣草,
                        单元格色彩标号.白色, 单元格色彩标号.紫色,
                        单元格色彩标号.白色, 单元格色彩标号.兰花);
                }
                return _紫色方案;
            }
        }

        private 配色方案 _当前配色方案 = null;

        public 配色方案 当前配色方案
        {
            get
            {
                if (_当前配色方案 == null)
                {
                    return 白色方案;
                }
                else return _当前配色方案;
            }
            set
            {
                _当前配色方案 = value;
            }
        }

        public 单元格字体 主标题单元格字体 { get { return 当前配色方案.主标题单元格字体; } }
        public 单元格字体 淡主标题单元格字体 { get { return 当前配色方案.淡主标题单元格字体; } }
        public 单元格字体 浅主标题单元格字体 { get { return 当前配色方案.浅主标题单元格字体; } }
        public 单元格字体 深主标题单元格字体 { get { return 当前配色方案.深主标题单元格字体; } }
        /// <summary>
        /// 主标题不带边框，加粗，宋体，20点，居中对齐
        /// </summary>
        public 单元格样式 主标题单元格样式 { get { return 当前配色方案.主标题单元格样式; } }
        public 单元格样式 淡主标题单元格样式 { get { return 当前配色方案.淡主标题单元格样式; } }
        public 单元格样式 浅主标题单元格样式 { get { return 当前配色方案.浅主标题单元格样式; } }
        public 单元格样式 深主标题单元格样式 { get { return 当前配色方案.深主标题单元格样式; } }

        public 单元格字体 副标题单元格字体 { get { return 当前配色方案.副标题单元格字体; } }
        public 单元格字体 淡副标题单元格字体 { get { return 当前配色方案.淡副标题单元格字体; } }
        public 单元格字体 浅副标题单元格字体 { get { return 当前配色方案.浅副标题单元格字体; } }
        public 单元格字体 深副标题单元格字体 { get { return 当前配色方案.深副标题单元格字体; } }
        /// <summary>
        /// 副标题不带边框，加粗，宋体，18点，居中对齐
        /// </summary>
        public 单元格样式 副标题单元格样式 { get { return 当前配色方案.副标题单元格样式; } }
        public 单元格样式 淡副标题单元格样式 { get { return 当前配色方案.淡副标题单元格样式; } }
        public 单元格样式 浅副标题单元格样式 { get { return 当前配色方案.浅副标题单元格样式; } }
        public 单元格样式 深副标题单元格样式 { get { return 当前配色方案.深副标题单元格样式; } }

        public 单元格字体 微标题单元格字体 { get { return 当前配色方案.微标题单元格字体; } }
        public 单元格字体 淡微标题单元格字体 { get { return 当前配色方案.淡微标题单元格字体; } }
        public 单元格字体 浅微标题单元格字体 { get { return 当前配色方案.浅微标题单元格字体; } }
        public 单元格字体 深微标题单元格字体 { get { return 当前配色方案.深微标题单元格字体; } }
        /// <summary>
        /// 副标题不带边框，加粗，宋体，15点，居中对齐
        /// </summary>
        public 单元格样式 微标题单元格样式 { get { return 当前配色方案.微标题单元格样式; } }
        public 单元格样式 淡微标题单元格样式 { get { return 当前配色方案.淡微标题单元格样式; } }
        public 单元格样式 浅微标题单元格样式 { get { return 当前配色方案.浅微标题单元格样式; } }
        public 单元格样式 深微标题单元格样式 { get { return 当前配色方案.深微标题单元格样式; } }

        public 单元格字体 较窄单元格字体 { get { return 当前配色方案.较窄单元格字体; } }
        public 单元格字体 淡较窄单元格字体 { get { return 当前配色方案.淡较窄单元格字体; } }
        public 单元格字体 浅较窄单元格字体 { get { return 当前配色方案.浅较窄单元格字体; } }
        public 单元格字体 深较窄单元格字体 { get { return 当前配色方案.深较窄单元格字体; } }
        /// <summary>
        /// 短文本带细线边框，宋体，不加粗，12点，居中对齐
        /// </summary>
        public 单元格样式 较窄单元格样式 { get { return 当前配色方案.较窄单元格样式; } }
        public 单元格样式 淡较窄单元格样式 { get { return 当前配色方案.淡较窄单元格样式; } }
        public 单元格样式 浅较窄单元格样式 { get { return 当前配色方案.浅较窄单元格样式; } }
        public 单元格样式 深较窄单元格样式 { get { return 当前配色方案.深较窄单元格样式; } }

        public 单元格字体 较宽单元格字体 { get { return 当前配色方案.较宽单元格字体; } }
        public 单元格字体 淡较宽单元格字体 { get { return 当前配色方案.淡较宽单元格字体; } }
        public 单元格字体 浅较宽单元格字体 { get { return 当前配色方案.浅较宽单元格字体; } }
        public 单元格字体 深较宽单元格字体 { get { return 当前配色方案.深较宽单元格字体; } }
        /// <summary>
        /// 长文本带细线边框，宋体，不加粗，12点，居左对齐
        /// </summary>
        public 单元格样式 较宽单元格样式 { get { return 当前配色方案.较宽单元格样式; } }
        public 单元格样式 淡较宽单元格样式 { get { return 当前配色方案.淡较宽单元格样式; } }
        public 单元格样式 浅较宽单元格样式 { get { return 当前配色方案.浅较宽单元格样式; } }
        public 单元格样式 深较宽单元格样式 { get { return 当前配色方案.深较宽单元格样式; } }

        public 单元格字体 默认单元格字体 { get { return 当前配色方案.默认单元格字体; } }
        public 单元格字体 淡默认单元格字体 { get { return 当前配色方案.淡默认单元格字体; } }
        public 单元格字体 浅默认单元格字体 { get { return 当前配色方案.浅默认单元格字体; } }
        public 单元格字体 深默认单元格字体 { get { return 当前配色方案.深默认单元格字体; } }
        /// <summary>
        /// 短文本带细线边框，宋体，不加粗，11点，居中对齐
        /// </summary>
        public 单元格样式 默认单元格样式 { get { return 当前配色方案.默认单元格样式; } }
        public 单元格样式 淡默认单元格样式 { get { return 当前配色方案.淡默认单元格样式; } }
        public 单元格样式 浅默认单元格样式 { get { return 当前配色方案.浅默认单元格样式; } }
        public 单元格样式 深默认单元格样式 { get { return 当前配色方案.深默认单元格样式; } }

        public 单元格字体 无框单元格字体 { get { return 当前配色方案.无框单元格字体; } }
        public 单元格字体 淡无框单元格字体 { get { return 当前配色方案.淡无框单元格字体; } }
        public 单元格字体 浅无框单元格字体 { get { return 当前配色方案.浅无框单元格字体; } }
        public 单元格字体 深无框单元格字体 { get { return 当前配色方案.深无框单元格字体; } }
        /// <summary>
        /// 短文本，不带边框，宋体，不加粗，11点，居中对齐
        /// </summary>
        public 单元格样式 无框单元格样式 { get { return 当前配色方案.无框单元格样式; } }
        public 单元格样式 淡无框单元格样式 { get { return 当前配色方案.淡无框单元格样式; } }
        public 单元格样式 浅无框单元格样式 { get { return 当前配色方案.浅无框单元格样式; } }
        public 单元格样式 深无框单元格样式 { get { return 当前配色方案.深无框单元格样式; } }

        #endregion

        public 单元格样式 定制单元格样式(string fontName, double fontSize,
            单元格色彩标号 foreColor = 单元格色彩标号.黑色, 单元格色彩标号 backColor = 单元格色彩标号.白色,
            bool isBold = false, bool isItalic = false, 单元格下划线类型 underLineType = 单元格下划线类型.无下划线,
            单元格水平对齐 hAlign = 单元格水平对齐.水平居中, 单元格垂直对齐 vAlign = 单元格垂直对齐.垂直居中,
            单元格边框类型 lBorderType = 单元格边框类型.细边框, 单元格边框类型 tBorderType = 单元格边框类型.细边框,
            单元格边框类型 rBorderType = 单元格边框类型.细边框, 单元格边框类型 bBorderType = 单元格边框类型.细边框,
            单元格色彩标号 lBorderColor = 单元格色彩标号.黑色, 单元格色彩标号 tBorderColor = 单元格色彩标号.黑色,
            单元格色彩标号 rBorderColor = 单元格色彩标号.黑色, 单元格色彩标号 bBorderColor = 单元格色彩标号.黑色)
        {
            var font = this.创建单元格字体();
            font.置单元格字体名(fontName);
            font.置单元格字号(fontSize);
            font.置单元格文本色彩(foreColor);
            font.置单元格加粗(isBold);
            font.置单元格倾斜(isItalic);
            font.置单元格下划线类型(underLineType);

            var style = this.创建单元格样式();
            style.置单元格字体(font);
            style.置单元格背景色(backColor);
            style.置水平对齐(hAlign);
            style.置垂直对齐(vAlign);
            style.置单元格左边框类型(lBorderType);
            style.置单元格左边框色(lBorderColor);
            style.置单元格上边框类型(tBorderType);
            style.置单元格上边框色(tBorderColor);
            style.置单元格右边框类型(rBorderType);
            style.置单元格右边框色(rBorderColor);
            style.置单元格下边框类型(bBorderType);
            style.置单元格下边框色(bBorderColor);

            return style;
        }

        /// <summary>
        /// 除前景色/背景色外，其它会使用“默认单元格样式”。
        /// </summary>
        /// <param name="foreColor">前景色标号。</param>
        /// <param name="backColor">背景色标号。</param>
        /// <returns></returns>
        public 单元格样式 定制彩色单元格样式(单元格色彩标号 foreColor, 单元格色彩标号 backColor)
        {
            return 定制单元格样式(默认单元格字体.字体.FontName, 默认单元格字体.字体.FontHeightInPoints, foreColor, backColor,
                默认单元格字体.字体.IsBold, 默认单元格字体.字体.IsItalic, 默认单元格字体.单元格下划线类型, 默认单元格样式.水平对齐, 默认单元格样式.垂直对齐,
                默认单元格样式.单元格左边框类型, 默认单元格样式.单元格上边框类型, 默认单元格样式.单元格右边框类型, 默认单元格样式.单元格下边框类型,
                默认单元格样式.单元格左边框色, 默认单元格样式.单元格上边框色, 默认单元格样式.单元格右边框色, 默认单元格样式.单元格下边框色);
        }
    }

    public class 配色方案
    {
        public 配色方案(string name, 工作簿管理器 workbook)
        {
            _方案名称 = name;
            _工作簿 = workbook;
        }

        private 工作簿管理器 _工作簿;

        public 工作簿管理器 工作簿
        {
            get { return _工作簿; }
        }

        private string _方案名称;

        public string 方案名称
        {
            get { return _方案名称; }
        }

        public 单元格字体 主标题单元格字体 { get; set; }
        public 单元格字体 淡主标题单元格字体 { get; set; }
        public 单元格字体 浅主标题单元格字体 { get; set; }
        public 单元格字体 深主标题单元格字体 { get; set; }
        /// <summary>
        /// 主标题不带边框，加粗，宋体，20点，居中对齐
        /// </summary>
        public 单元格样式 主标题单元格样式 { get; set; }
        public 单元格样式 淡主标题单元格样式 { get; set; }
        public 单元格样式 浅主标题单元格样式 { get; set; }
        public 单元格样式 深主标题单元格样式 { get; set; }

        public 单元格字体 副标题单元格字体 { get; set; }
        public 单元格字体 淡副标题单元格字体 { get; set; }
        public 单元格字体 浅副标题单元格字体 { get; set; }
        public 单元格字体 深副标题单元格字体 { get; set; }
        /// <summary>
        /// 副标题不带边框，加粗，宋体，18点，居中对齐
        /// </summary>
        public 单元格样式 副标题单元格样式 { get; set; }
        public 单元格样式 淡副标题单元格样式 { get; set; }
        public 单元格样式 浅副标题单元格样式 { get; set; }
        public 单元格样式 深副标题单元格样式 { get; set; }

        public 单元格字体 微标题单元格字体 { get; set; }
        public 单元格字体 淡微标题单元格字体 { get; set; }
        public 单元格字体 浅微标题单元格字体 { get; set; }
        public 单元格字体 深微标题单元格字体 { get; set; }
        /// <summary>
        /// 副标题不带边框，加粗，宋体，15点，居中对齐
        /// </summary>
        public 单元格样式 微标题单元格样式 { get; set; }
        public 单元格样式 淡微标题单元格样式 { get; set; }
        public 单元格样式 浅微标题单元格样式 { get; set; }
        public 单元格样式 深微标题单元格样式 { get; set; }

        public 单元格字体 较窄单元格字体 { get; set; }
        public 单元格字体 淡较窄单元格字体 { get; set; }
        public 单元格字体 浅较窄单元格字体 { get; set; }
        public 单元格字体 深较窄单元格字体 { get; set; }
        /// <summary>
        /// 短文本带细线边框，宋体，不加粗，12点，居中对齐
        /// </summary>
        public 单元格样式 较窄单元格样式 { get; set; }
        public 单元格样式 淡较窄单元格样式 { get; set; }
        public 单元格样式 浅较窄单元格样式 { get; set; }
        public 单元格样式 深较窄单元格样式 { get; set; }

        public 单元格字体 较宽单元格字体 { get; set; }
        public 单元格字体 淡较宽单元格字体 { get; set; }
        public 单元格字体 浅较宽单元格字体 { get; set; }
        public 单元格字体 深较宽单元格字体 { get; set; }
        /// <summary>
        /// 长文本带细线边框，宋体，不加粗，12点，居左对齐
        /// </summary>
        public 单元格样式 较宽单元格样式 { get; set; }
        public 单元格样式 淡较宽单元格样式 { get; set; }
        public 单元格样式 浅较宽单元格样式 { get; set; }
        public 单元格样式 深较宽单元格样式 { get; set; }

        public 单元格字体 默认单元格字体 { get; set; }
        public 单元格字体 淡默认单元格字体 { get; set; }
        public 单元格字体 浅默认单元格字体 { get; set; }
        public 单元格字体 深默认单元格字体 { get; set; }
        /// <summary>
        /// 短文本带细线边框，宋体，不加粗，11点，居中对齐
        /// </summary>
        public 单元格样式 默认单元格样式 { get; set; }
        public 单元格样式 淡默认单元格样式 { get; set; }
        public 单元格样式 浅默认单元格样式 { get; set; }
        public 单元格样式 深默认单元格样式 { get; set; }

        public 单元格字体 无框单元格字体 { get; set; }
        public 单元格字体 淡无框单元格字体 { get; set; }
        public 单元格字体 浅无框单元格字体 { get; set; }
        public 单元格字体 深无框单元格字体 { get; set; }
        /// <summary>
        /// 短文本，不带边框，宋体，不加粗，11点，居中对齐
        /// </summary>
        public 单元格样式 无框单元格样式 { get; set; }
        public 单元格样式 淡无框单元格样式 { get; set; }
        public 单元格样式 浅无框单元格样式 { get; set; }
        public 单元格样式 深无框单元格样式 { get; set; }
    }

    public class 工作表
    {
        internal 工作表(ISheet iSheet)
        {
            this._工作表体 = iSheet;
        }

        public int 最大行数
        {
            get
            {
                if (_工作表体 == null) return 0;

                if (_工作表体 is XSSFWorkbook)   // 2007+ 以上格式
                {
                    return 1048576;
                }
                else return 65536;
            }
        }

        public int 最大列数
        {
            get
            {
                if (_工作表体 == null) return 0;

                if (_工作表体 is XSSFWorkbook)   // 2007+ 以上格式
                {
                    return 16384;
                }
                else return 256;
            }
        }

        private 工作簿管理器 _父工作簿 = null;

        public 工作簿管理器 父工作簿
        {
            get { return _父工作簿; }
            internal set { _父工作簿 = value; }
        }

        public 工作簿管理器 所属工作簿
        {
            get => _父工作簿;
        }

        private ISheet _工作表体;

        public ISheet 工作表体
        {
            get { return _工作表体; }
        }

        public string 工作表名字
        {
            get { return _工作表体.SheetName; }
            set
            {
                if (this._工作表体 != null && this._工作表体.Workbook != null)
                {
                    this._工作表体.Workbook.SetSheetName(this._工作表体.Workbook.GetSheetIndex(this._工作表体), value);
                }
            }
        }

        public string 工作表名称
        {
            get { return _工作表体.SheetName; }
            set
            {
                if (this._工作表体 != null && this._工作表体.Workbook != null)
                {
                    this._工作表体.Workbook.SetSheetName(this._工作表体.Workbook.GetSheetIndex(this._工作表体), value);
                }
            }
        }

        public int 工作表索引
        {
            get
            {
                if (this._工作表体 != null && this._工作表体.Workbook != null)
                {
                    return this._工作表体.Workbook.GetSheetIndex(this._工作表体);
                }

                return -1;
            }
        }

        public 行 创建行(int rowIndex)
        {
            if (rowIndex < 0) { rowIndex = 0; }

            var maxRowIndex = _工作表体.LastRowNum - 1;

            if (maxRowIndex < rowIndex)
            {
                for (int i = maxRowIndex + 1; i <= rowIndex - 1; i++)
                {
                    _工作表体.CreateRow(i + 1);
                }
            }

            var row = this._工作表体.CreateRow(rowIndex);
            if (row == null) return null;

            return new 行(row, this);
        }

        public 行 取字段名行(区域 dataRng = null)
        {
            if (dataRng == null)
            {
                dataRng = 数据区域;
            }

            if (dataRng.区域体.FirstRow < 0)
                throw new Exception("数据区域非法，首行索引小于 0。");

            if (dataRng.区域体.FirstRow > 最大行数 - 1)
                throw new Exception("数据区域非法，首行索引大于当前文档格式支持的最大行索引。");

            if (dataRng.区域体.LastRow < 0)
                throw new Exception("数据区域非法，首行索引小于 0。");

            if (dataRng.区域体.LastRow > 最大行数 - 1)
                throw new Exception("数据区域非法，首行索引大于当前文档格式支持的最大行索引。");

            if (dataRng.区域体.LastRow < dataRng.区域体.FirstRow)
                throw new Exception("数据区域非法，尾行索引小于首行索引。");

            if (dataRng.区域体.FirstColumn < 0)
                throw new Exception("数据区域非法，首列索引小于 0。");

            if (dataRng.区域体.FirstColumn > 最大列数 - 1)
                throw new Exception("数据区域非法，首列索引大于当前文档格式支持的最大列索引。");

            if (dataRng.区域体.LastColumn < 0)
                throw new Exception("数据区域非法，首列索引小于 0。");

            if (dataRng.区域体.LastColumn > 最大列数 - 1)
                throw new Exception("数据区域非法，首列索引大于当前文档格式支持的最大列索引。");

            if (dataRng.区域体.LastColumn < dataRng.区域体.FirstColumn)
                throw new Exception("数据区域非法，尾列索引小于首列索引。");

            var row = 取行(dataRng.区域体.FirstRow);
            if (row == null)
                throw new Exception("未能找到字段名行。");

            return row;
        }

        public PythonList 取字段名列表()
        {
            var dataRng = this.数据区域;
            if (dataRng == null) return null;

            var row = 取字段名行(dataRng);

            var fieldNames = new PythonList();

            for (int i = dataRng.区域体.FirstColumn; i <= dataRng.区域体.LastColumn; i++)
            {
                var cell = row.取单元格(i);
                if (cell == null || cell.文本值 == null)
                {
                    fieldNames.Add(null);
                    continue;
                }

                fieldNames.Add(cell.文本值);
            }

            return fieldNames;
        }

        public 行 取行(int rowIndex)
        {
            var row = this._工作表体.GetRow(rowIndex);
            if (row == null)
            {
                var 行 = 创建行(rowIndex);
                row = 行.行体;
            }

            return new 行(row, this);
        }

        public string 取字段值(int rowIndex, string 字段名, bool ignoreCase = true)
        {
            var row = this.取行(rowIndex);
            if (row == null) return null;

            return row.取字段值(字段名, ignoreCase);
        }

        /// <summary>
        /// 此方法按指定的字段名和字段值在数据区域查找数据行。
        /// 注意：此方法只会返回第一个找到的行，而忽略其后的所有行——因此只适用于没有重复值的行。
        /// </summary>
        /// <param name="字段名">如果为 null 会视为空字符串。</param>
        /// <param name="字段值">如果为 null 会视为空字符串。</param>
        /// <returns></returns>
        public 行 按字段值查找行(string 字段名, string 字段值, bool 忽略大小写 = true)
        {
            if (字段名 == null) 字段名 = "";
            if (字段值 == null) 字段值 = "";

            var dataRng = this.数据区域;
            if (dataRng == null)
                throw new Exception("当前工作表中不存在有效的数据区域。");

            var firstRow = Math.Min(dataRng.首行索引, dataRng.尾行索引);
            var lastRow = Math.Max(dataRng.首行索引, dataRng.尾行索引);
            var firstColumn = Math.Min(dataRng.首列索引, dataRng.尾列索引);
            var lastColumn = Math.Max(dataRng.首列索引, dataRng.尾列索引);

            var fieldRow = this.取字段名行();
            if (fieldRow == null)
                throw new Exception("未能在当前数据区域找到字段名行。");

            var fieldCell = fieldRow.取字段名单元格(字段名, 忽略大小写);
            if (fieldCell == null)
            {
                if (字段名 == "")
                {
                    throw new Exception("未能找到字段名为空字符串的字段。");
                }
                else
                {
                    throw new Exception($"未能找到字段名为【{字段名}】的字段。");
                }
            }

            var fieldColIndex = fieldCell.单元格体.ColumnIndex;

            for (int rowIndex = firstRow + 1; rowIndex <= lastRow; rowIndex++)  // 第一行视为字段名行
            {
                var row = this.取行(rowIndex);

                var cell = row.取单元格(fieldColIndex);
                if (cell == null) continue;

                var cellValue = cell.文本值;
                if (cellValue == null) continue;

                if (忽略大小写)
                {
                    if (cellValue.ToLower() == 字段值.ToLower()) return row;
                }
                else
                {
                    if (cellValue == 字段值) return row;
                }
            }

            return null;
        }

        public PythonList 取连续单元格文本列表(int rowIndex, int colIndex, int cellCount)
        {
            if (rowIndex < 0)
                throw new Exception("行索引不能小于 0。");

            var maxRowIndex = this.最大行数 - 1;
            if (rowIndex > maxRowIndex)
                throw new Exception($"行索引不能大于当前文档格式支持的最大行索引 {maxRowIndex}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("未能从当前工作表中获取指定位置处的行。");

            return row.取连续单元格文本列表(colIndex, cellCount);
        }

        /// <summary>
        /// 此方法返回一个双层列表，外层列表中每个成员（内层列表）表示区域中一行，内层列表中每个成员表示一个单元格的文本值。
        /// 
        /// 注意：外层列表不会为 null，但内层列表可能为 null，内层列表的成员也可能为 null。
        /// </summary>
        /// <param name="rng"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public PythonList 取区域文本列表(区域 rng)
        {
            if (rng == null || rng.区域体 == null)
                throw new Exception("指定区域非法。");

            if (rng.首行索引 < 0 || rng.首行索引 >= 最大行数)
                throw new Exception($"区域首行索引非法。首行索引必须在 0-{最大行数 - 1}之间。");

            if (rng.首列索引 < 0 || rng.首列索引 >= 最大列数)
                throw new Exception($"区域首列索引非法。首列索引必须在 0-{最大列数 - 1}之间。");

            if (rng.尾行索引 < 0 || rng.尾行索引 >= 最大行数)
                throw new Exception($"区域尾行索引非法。尾行索引必须在 0-{最大行数 - 1}之间。");

            if (rng.尾列索引 < 0 || rng.尾列索引 >= 最大列数)
                throw new Exception($"区域尾列索引非法。尾列索引必须在 0-{最大列数 - 1}之间。");

            var srcFirstRow = Math.Min(rng.首行索引, rng.尾行索引);
            var srcLastRow = Math.Max(rng.首行索引, rng.尾行索引);
            var srcFirstColumn = Math.Min(rng.首列索引, rng.尾列索引);
            var srcLastColumn = Math.Max(rng.首列索引, rng.尾列索引);

            var list = new PythonList();

            for (int rowIndex = srcFirstRow; rowIndex <= srcLastRow; rowIndex++)
            {
                var row = this.取行(rowIndex);
                if (row == null)
                {
                    list.Add(null);
                    continue;
                }

                var subList = new PythonList();

                for (int colIndex = srcFirstColumn; colIndex <= srcLastColumn; colIndex++)
                {
                    var cell = row.取单元格(colIndex);
                    if (cell == null)
                    {
                        subList.Add(null);
                        continue;
                    }

                    subList.Add(cell.文本值);
                }
                list.Add(subList);
            }

            return list;
        }

        public PythonList 取区域文本列表(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex)
        {
            return 取区域文本列表(取区域(firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex));
        }

        public PythonList 取区域文本列表(string regionMark)
        {
            var region = 取区域(regionMark);
            if (region == null)
                throw new Exception("区域标记文本非法，无法识别。");

            return 取区域文本列表(region);
        }

        /// <summary>
        /// 将“取区域文本列表”得到的数据填充到当前工作表中指定位置。
        /// 之所以没有在当前工作表中实现类似“复制区域到其它工作表”的功能，是因为在当前工作表中复制区域可能破坏源数据区域的格式。
        /// “复制区域到其它工作表”是带格式复制的（由于NPOI的限制不是100%）。
        /// </summary>
        /// <param name="list">应传入一个双层列表。外层表示一个区域，内层列表表示一行，内层列表的成员表示一个单元格。</param>
        /// <param name="destRegion">只使用区域左上角定位。</param>
        /// <returns>返回自身，方便链式调用。</returns>
        public 工作表 填充区域文本列表(PythonList list, 区域 destRegion)
        {
            if (list == null)
                throw new Exception("应传入一个双层列表。");

            if (destRegion == null)
                throw new Exception("指定区域不能为 None。");

            var firstRow = Math.Min(destRegion.首行索引, destRegion.尾行索引);
            var lastRow = Math.Max(destRegion.首行索引, destRegion.尾行索引);
            var firstColumn = Math.Min(destRegion.首列索引, destRegion.尾列索引);
            var lastColumn = Math.Max(destRegion.首列索引, destRegion.尾列索引);

            lastRow = firstRow + list.Count - 1;

            var maxColumnOfSubList = 0;
            foreach (var item in list)
            {
                if (item == null) continue;

                var subList = item as PythonList;
                if (subList == null)
                {
                    maxColumnOfSubList = Math.Max(maxColumnOfSubList, 1);
                }
                else
                {
                    maxColumnOfSubList = Math.Max(maxColumnOfSubList, subList.Count);
                }
            }

            if (maxColumnOfSubList <= 0)
                throw new Exception("列表中所有成员的长度均小于1，此操作无意义。");

            lastColumn = firstColumn + maxColumnOfSubList - 1;

            var maxRowIndex = 最大行数 - 1;
            var maxColumnIndex = 最大列数 - 1;

            if (firstRow < 0 || firstRow > maxRowIndex)
                throw new Exception($"指定区域首行索引不能小于0或大于{maxRowIndex}。");
            if (lastRow < 0 || lastRow > maxRowIndex)
                throw new Exception($"指定区域尾行索引不能小于0或大于{maxRowIndex}。");        // 此值由列表计算而来，不是由 destRegion 指定的

            if (firstColumn < 0 || firstColumn > maxColumnIndex)
                throw new Exception($"指定区域首列索引不能小于0或大于{maxColumnIndex}。");
            if (lastColumn < 0 || lastColumn > maxColumnIndex)
                throw new Exception($"指定区域尾列索引不能小于0或大于{maxColumnIndex}。");       // 此值由列表计算而来，不是由 destRegion 指定的

            for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++)
            {
                var item = list[rowIndex - firstRow];
                if (item == null) continue;

                var subList = item as PythonList;
                if (subList == null)
                {
                    // 其它对象
                    this.取单元格(rowIndex, firstColumn).置文本值(item.ToString());
                }
                else
                {
                    // 子列表对象
                    if (subList.Count <= 0) continue;

                    for (int colIndex = firstColumn; colIndex <= Math.Min(subList.Count + firstColumn - 1, lastColumn); colIndex++)
                    {
                        var subItem = subList[colIndex - firstColumn];
                        if (subItem == null) continue;

                        this.取单元格(rowIndex, colIndex).置文本值(subItem.ToString());
                    }
                }
            }

            return this;
        }

        public 工作表 填充区域文本列表(PythonList list, string regionMark)
        {
            var region = 取区域(regionMark);

            if (region == null)
                throw new Exception("区域标记非法。");

            return 填充区域文本列表(list, region);
        }

        public 工作表 填充区域文本列表(PythonList list, int rowIndex, int colIndex)
        {
            var region = new 区域(rowIndex, rowIndex, colIndex, colIndex);
            return 填充区域文本列表(list, region);
        }

        public 工作表 向右填充字段(int rowIndex, int colIndex, string[] values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向右填充字段(colIndex, values, reverse);
            return this;
        }

        public 工作表 向右填充字段(int rowIndex, int colIndex, PythonList values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向右填充字段(colIndex, values, reverse);
            return this;
        }

        public 工作表 向右填充字段(int rowIndex, int colIndex, PythonTuple values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向右填充字段(colIndex, values, reverse);
            return this;
        }

        public 工作表 向左填充字段(int rowIndex, int colIndex, string[] values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向左填充字段(colIndex, values, reverse);
            return this;
        }

        public 工作表 向左填充字段(int rowIndex, int colIndex, PythonList values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向左填充字段(colIndex, values, reverse);
            return this;
        }

        public 工作表 向左填充字段(int rowIndex, int colIndex, PythonTuple values, bool reverse = false)
        {
            if (rowIndex < 0)
                throw new Exception("行号不能小于 0。");

            if (rowIndex > this.最大行数 - 1)
                throw new Exception($"行号不能大于当前文档格式支持的最大行索引{this.最大行数 - 1}。");

            var row = this.取行(rowIndex);
            if (row == null)
                throw new Exception("在指定行索引位置处未能获取工作表行。");

            row.向左填充字段(colIndex, values, reverse);
            return this;
        }

        public PythonList 筛选同名字段值(int rowIndex, string fieldName, bool ignoreCase = true)
        {
            if (string.IsNullOrEmpty(fieldName)) return null;   // 字段值可以为空或Null，但字段名不能为空字符串

            var row = this.取行(rowIndex);
            if (row == null) return null;

            var dataRng = 数据区域;
            if (dataRng == null) return null;

            var fieldsRow = 取行(dataRng.区域体.FirstRow);
            if (fieldsRow == null) return null;

            var list = new PythonList();
            for (int i = dataRng.区域体.FirstColumn; i <= dataRng.区域体.LastColumn; i++)
            {
                var fieldCell = fieldsRow.取单元格(i);
                if (fieldCell == null || string.IsNullOrEmpty(fieldCell.文本值)) continue;

                if (ignoreCase)
                {
                    if (fieldCell.文本值.ToLower() == fieldName.ToLower())  // 字段名不能为空或null
                    {
                        list.Add(row.取单元格(i).文本值);   // 字段值可以为 空字符串或 null
                    }
                }
                else
                {
                    if (fieldCell.文本值 == fieldName)    // 字段名不能为空或null
                    {
                        list.Add(row.取单元格(i).文本值);
                    }
                }
            }
            return list;
        }

        public IronPython.Runtime.PythonList 筛选字段值(int rowIndex, string[] fields, bool ignoreCase = true)
        {
            var row = this.取行(rowIndex);
            if (row == null) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(row.取字段值(field, ignoreCase));
            }
            return list;
        }

        public IronPython.Runtime.PythonList 筛选字段值(int rowIndex, IronPython.Runtime.PythonTuple fields, bool ignoreCase = true)
        {
            var row = this.取行(rowIndex);
            if (row == null) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(row.取字段值(field as string, ignoreCase));
            }
            return list;
        }

        public IronPython.Runtime.PythonList 筛选字段值(int rowIndex, IronPython.Runtime.PythonList fields, bool ignoreCase = true)
        {
            var row = this.取行(rowIndex);
            if (row == null) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(row.取字段值(field as string, ignoreCase));
            }
            return list;
        }

        public int 取物理行数()
        {
            return _工作表体.PhysicalNumberOfRows;
        }

        public int 物理行数
        {
            get => _工作表体.PhysicalNumberOfRows;
        }

        public CellRangeAddress GetUsedRange(ISheet sheet)
        {
            // 1. 获取行范围
            int firstRow = sheet.FirstRowNum;
            int lastRow = sheet.LastRowNum;

            // 空工作表处理
            if (lastRow < 0) return null;

            // 2. 初始化列边界
            int firstCol = 最大列数 - 1;
            int lastCol = 0;

            // 3. 遍历所有行
            for (int rowIdx = firstRow; rowIdx <= lastRow; rowIdx++)
            {
                IRow row = sheet.GetRow(rowIdx);
                if (row == null) continue; // 跳过空行

                // 更新列边界
                if (row.FirstCellNum >= 0 && row.FirstCellNum < firstCol)
                    firstCol = row.FirstCellNum;

                if (row.LastCellNum > lastCol)
                    lastCol = row.LastCellNum;
            }

            // 4. 处理无有效列的情况
            if (firstCol == 最大列数 - 1 || lastCol == 0)
                return null;

            // 5. 返回单元格范围 (注意: LastCellNum是下个空单元格索引，需-1)
            return new CellRangeAddress(
                firstRow,
                lastRow,
                firstCol,
                lastCol - 1  // 修正为实际最后列索引
            );
        }

        public 区域 已用区域
        {
            get
            {
                var range = GetUsedRange(this._工作表体);
                if (range == null) return null;

                return new 区域(range.FirstRow, range.LastRow, range.FirstColumn, range.LastColumn);
            }
        }

        /// <summary>
        /// 只返回包含非空单元格的范围。
        /// 列索引是从 0 开始的（A=0, B=1,...）
        /// </summary>
        /// <returns></returns>
        public 区域 取数据区域()
        {
            if (_工作表体 == null || _工作表体.PhysicalNumberOfRows == 0)
            {
                return null;
            }

            int firstRow = _工作表体.FirstRowNum;
            int lastRow = _工作表体.LastRowNum;
            int firstCol = 最大列数 - 1;
            int lastCol = 0;

            for (int rowNum = firstRow; rowNum <= lastRow; rowNum++)
            {
                IRow row = _工作表体.GetRow(rowNum);
                if (row != null)
                {
                    for (int colNum = row.FirstCellNum; colNum < row.LastCellNum; colNum++)
                    {
                        ICell cell = row.GetCell(colNum);
                        if (cell != null && cell.CellType != NPOI.SS.UserModel.CellType.Blank)
                        {
                            if (colNum < firstCol) firstCol = colNum;
                            if (colNum > lastCol) lastCol = colNum;
                        }
                    }
                }
            }

            if (firstCol == 最大列数 - 1)
            {
                return null;
            }

            return new 区域(firstRow, lastRow, firstCol, lastCol);
        }

        private 区域 _数据区域 = null;

        /// <summary>
        /// 只返回包含非空单元格的范围。
        /// 列索引是从 0 开始的（A=0, B=1,...）
        /// </summary>
        public 区域 数据区域
        {
            get
            {
                if (_数据区域 != null)
                {
                    return _数据区域;
                }
                else return 取数据区域();
            }
            set
            {
                _数据区域 = value;
            }
        }

        /// <summary>
        /// 写错了，为兼容旧代码保留。应为“非空白行数”。
        /// </summary>
        public int 非白空行数
        {
            get => _工作表体.PhysicalNumberOfRows;
        }

        public int 非空白行数
        {
            get => _工作表体.PhysicalNumberOfRows;
        }

        public int 取最大行索引()
        {
            return _工作表体.LastRowNum;
        }

        public int 取最大行号()
        {
            return _工作表体.LastRowNum;
        }

        public int 最大行索引
        {
            get => _工作表体.LastRowNum;
        }

        public int 最大行号
        {
            get => _工作表体.LastRowNum;
        }

        public int 取最小行索引()
        {
            return _工作表体.FirstRowNum;
        }

        public int 最小行索引()
        {
            return _工作表体.FirstRowNum;
        }

        public 单元格样式 创建单元格样式(单元格字体 cellFont = null)
        {
            var cellStyle = new 单元格样式(_工作表体.Workbook.CreateCellStyle());
            if (cellFont != null)
            {
                cellStyle.置单元格字体(cellFont);
            }
            return cellStyle;
        }

        public 单元格字体 创建单元格字体()
        {
            return new 单元格字体(_工作表体.Workbook.CreateFont());
        }

        public 单元格 取单元格(int rowIndex, int columnIndex, bool autoCreate = true)
        {
            try
            {
                var row = _工作表体.GetRow(rowIndex);
                行 行;
                if (row == null)
                {
                    if (autoCreate == false) return null;

                    行 = this.创建行(rowIndex);
                    row = 行.行体;
                }
                else
                {
                    行 = new 行(row, this);
                }

                var cell = row.GetCell(columnIndex);
                if (cell == null)
                {
                    if (autoCreate == false) return null;

                    cell = 行.创建单元格(columnIndex).单元格体;
                }

                return new 单元格(cell, this, 行);
            }
            catch { return null; }
        }

        public 单元格 取单元格(string regionMark, bool autoCreate = true)
        {
            if (string.IsNullOrWhiteSpace(regionMark))
                throw new Exception("不能识别的单元格位置标记。");

            regionMark = regionMark.Trim();

            var regCell = new Regex(@"[a-zA-Z]{1,3}\d+");
            var matchCell = regCell.Match(regionMark);
            if (matchCell.Success == false)
                throw new Exception("不能识别的单元格位置标记。");

            var cellRef = new CellReference(regionMark);
            var cell = 取单元格(cellRef.Row, cellRef.Col, autoCreate);
            return cell;
        }

        public 工作表 置单元格值(string regionMark, double value)
        {
            var cell = 取单元格(regionMark, true);
            cell.置单元格值(value);
            return this;
        }

        public 工作表 置单元格值(单元格 cell, double value)
        {
            if (cell != null)
                cell.置单元格值(value);

            return this;
        }

        public 区域 取区域(string regionMark)
        {
            return new 区域(regionMark);
        }

        public 区域 取区域(int fstRow, int lastRow, int fstCol, int lastCol)
        {
            return new 区域(Math.Min(fstRow, lastRow), Math.Max(fstRow, lastRow),
                Math.Min(fstCol, lastCol), Math.Max(fstCol, lastCol));
        }

        public 工作表 置区域值(string regionMark, double value, bool autoCreateCell = true)
        {
            return 置区域双精度值(regionMark, value, autoCreateCell);
        }

        public 工作表 置区域值(区域 region, double value, bool autoCreateCell = true)
        {
            return 置区域双精度值(region, value, autoCreateCell);
        }

        public 工作表 置单元格文本值(string regionMark, string value)
        {
            var cell = 取单元格(regionMark, true);
            cell.置文本值(value);
            return this;
        }

        public 工作表 置单元格图像(string regionMark, string imageFilePath)
        {
            if (File.Exists(imageFilePath) == false)
                throw new Exception("图像文件不存在。");

            var cell = 取单元格(regionMark, true);
            if (cell == null)
                throw new Exception("未找到指定单元格。");

            cell.置单元格图像(imageFilePath);
            return this;
        }

        public 工作表 置单元格图像(string regionMark, Bitmap bitmap)
        {
            if (bitmap == null)
                throw new Exception("图像数据参数不能为 None。");

            var cell = 取单元格(regionMark, true);
            if (cell == null)
                throw new Exception("未找到指定单元格。");

            cell.置单元格图像(bitmap);
            return this;
        }

        public 工作表 置单元格文本值(单元格 cell, string value)
        {
            if (cell != null)
                cell.置文本值(value);

            return this;
        }

        public 工作表 置单元格文本值(int rowIndex, int colIndex, string value)
        {
            var cell = 取单元格(rowIndex, colIndex, true);
            cell.置文本值(value);
            return this;
        }

        public 工作表 置区域文本值(string regionMark, string value, bool autoCreateCell = true)
        {
            return 置区域文本值(取区域(regionMark), value, autoCreateCell);
        }

        public 工作表 置区域文本值(区域 region, string value, bool autoCreateCell = true)
        {
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = region.区域体.LastColumn;
            var top = region.区域体.FirstRow;
            var bottom = region.区域体.LastRow;

            for (int i = top; i <= bottom; i++)
            {
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置文本值(value);
                    }
                }
            }
            return this;
        }

        /// <summary>
        /// 将指定文本数据行中所有数据以文本的形式填充到工作表指定区域。
        /// 注意：这里只使用指定区域的左上角单元格来定位，具体填充哪些单元格，由指定区域左上角和文本数据行中单元格的数量决定。
        ///       因此，如果文本数据行较长，而指定区域左上角又较靠右，可能超出 Excel 最大列数，从而导致出错。
        /// </summary>
        /// <param name="regionMark">指定要填充的区域（只使用其左上角单元格作为基准位置）。</param>
        /// <param name="dataRow">要填充的文本数据行，其中应包括一到多个单元格。</param>
        /// <param name="autoCreateCell">是否自动创建单元格，默认为 true。</param>
        /// <returns></returns>
        public 工作表 填充文本数据行(string regionMark, 文本数据行 dataRow, bool autoCreateCell = true)
        {
            return 填充文本数据行(取区域(regionMark), dataRow, autoCreateCell);
        }

        /// <summary>
        /// 将指定文本数据行中所有数据以文本的形式填充到工作表指定区域。
        /// 注意：这里只使用指定区域的左上角单元格来定位，具体填充哪些单元格，由指定区域左上角和文本数据行中单元格的数量决定。
        ///       因此，如果文本数据行较长，而指定区域左上角又较靠右，可能超出 Excel 最大列数，从而导致出错。
        /// </summary>
        /// <param name="region">指定要填充的区域（只使用其左上角单元格作为基准位置）。</param>
        /// <param name="dataRow">要填充的文本数据行，其中应包括一到多个单元格。</param>
        /// <param name="autoCreateCell">是否自动创建单元格，默认为 true。</param>
        /// <returns></returns>
        public 工作表 填充文本数据行(区域 region, 文本数据行 dataRow, bool autoCreateCell = true)
        {
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = left + dataRow.数据数组.Length;
            var top = region.区域体.FirstRow;

            for (int colIndex = left; colIndex < right; colIndex++)
            {
                var cell = this.取单元格(top, colIndex, autoCreateCell);
                if (cell != null)
                {
                    cell.置文本值(dataRow.按索引取值(colIndex - left));
                }
            }
            return this;
        }

        public 工作表 填充文本数据行(int top, int left, 文本数据行 dataRow, bool autoCreateCell = true)
        {
            var right = left + dataRow.数据数组.Length;

            for (int colIndex = left; colIndex < right; colIndex++)
            {
                var cell = this.取单元格(top, colIndex, autoCreateCell);
                if (cell != null)
                {
                    cell.置文本值(dataRow.按索引取值(colIndex - left));
                }
            }
            return this;
        }

        public 工作表 填充文本数据表(string regionMark, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            return 填充文本数据表(取区域(regionMark), dataTable, fillFieldNames, autoCreateCell);
        }

        public 工作表 填充文字表(string regionMark, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            return 填充文本数据表(取区域(regionMark), dataTable, fillFieldNames, autoCreateCell);
        }

        /// <summary>
        /// 将指定文本数据表中的内容填充到当前工作表指定位置。
        /// </summary>
        /// <param name="region">指定要填充的位置（只使用其左上角，其它会被忽略）。</param>
        /// <param name="dataTable">要填充的文本数据表。</param>
        /// <param name="fillFieldNames">是否填充字段名行。</param>
        /// <param name="autoCreateCell">是否自动创建单元格，默认为 true。</param>
        /// <returns></returns>
        public 工作表 填充文本数据表(区域 region, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            if (region == null || dataTable == null) return this;

            if (dataTable.字段名行 == null && dataTable.行数 <= 0) return this;

            var left = region.区域体.FirstColumn;
            var right = left + dataTable.列数;
            int top;
            int bottom;
            if (fillFieldNames == true && dataTable.首行是字段名列表)
            {
                // 只有这种情况，才需要额外添加首行
                var fieldNamesRowIndex = region.区域体.FirstRow;

                var dataRow = dataTable.字段名行;
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(fieldNamesRowIndex, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置文本值(dataRow.按索引取值(j - left));
                    }
                }

                top = region.区域体.FirstRow + 1;
                bottom = top + dataTable.行数 + 1;

            }
            else
            {
                // 其它情况直接填充所有行即可。
                top = region.区域体.FirstRow;
                bottom = top + dataTable.行数;
            }

            for (int i = top; i <= bottom; i++)
            {
                var dataRow = dataTable[i - top];
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置文本值(dataRow.按索引取值(j - left));
                    }
                }
            }

            return this;
        }

        public 工作表 填充文字表(区域 region, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            return 填充文本数据表(region, dataTable, fillFieldNames, autoCreateCell);
        }

        public 工作表 填充文本数据表(int baseTop, int left, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            if (dataTable == null) return this;

            if (dataTable.字段名行 == null && dataTable.行数 <= 0) return this;

            var right = left + dataTable.列数;
            int top;
            int bottom;

            if (fillFieldNames == true && dataTable.首行是字段名列表)
            {
                // 只有这种情况，才需要额外添加首行
                var fieldNamesRowIndex = baseTop;

                var dataRow = dataTable.字段名行;
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(fieldNamesRowIndex, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置文本值(dataRow.按索引取值(j - left));
                    }
                }

                top = baseTop + 1;
                bottom = top + dataTable.行数 + 1;

            }
            else
            {
                // 其它情况直接填充所有行即可。
                top = baseTop;
                bottom = top + dataTable.行数;
            }

            for (int i = top; i <= bottom; i++)
            {
                var dataRow = dataTable[i - top];
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置文本值(dataRow.按索引取值(j - left));
                    }
                }
            }

            return this;
        }

        public 工作表 填充文字表(int baseTop, int left, 文本数据表 dataTable, bool fillFieldNames, bool autoCreateCell = true)
        {
            return 填充文本数据表(baseTop, left, dataTable, fillFieldNames, autoCreateCell);
        }

        public 工作表 置单元格布尔值(string regionMark, bool value)
        {
            var cell = 取单元格(regionMark, true);
            cell.置布尔值(value);
            return this;
        }

        public 工作表 置单元格布尔值(单元格 cell, bool value)
        {
            if (cell != null)
                cell.置布尔值(value);

            return this;
        }

        public 工作表 置区域布尔值(string regionMark, bool value, bool autoCreateCell = true)
        {
            var region = 取区域(regionMark);
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = region.区域体.LastColumn;
            var top = region.区域体.FirstRow;
            var bottom = region.区域体.LastRow;

            for (int i = top; i <= bottom; i++)
            {
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置布尔值(value);
                    }
                }
            }
            return this;
        }

        public 工作表 置单元格日期时间值(string regionMark, int year, int month, int day, int hour, int minute, int second)
        {
            var cell = 取单元格(regionMark, true);
            cell.置日期时间值(year, month, day, hour, minute, second);
            return this;
        }

        public 工作表 置单元格日期时间值(单元格 cell, int year, int month, int day, int hour, int minute, int second)
        {
            if (cell != null)
                cell.置日期时间值(year, month, day, hour, minute, second);

            return this;
        }
        public 工作表 置区域日期时间值(string regionMark, int year, int month, int day, int hour, int minute, int second, bool autoCreateCell = true)
        {
            return 置区域日期时间值(取区域(regionMark), year, month, day, hour, minute, second, autoCreateCell);
        }

        public 工作表 置区域日期时间值(区域 region, int year, int month, int day, int hour, int minute, int second, bool autoCreateCell = true)
        {
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = region.区域体.LastColumn;
            var top = region.区域体.FirstRow;
            var bottom = region.区域体.LastRow;

            for (int i = top; i <= bottom; i++)
            {
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置日期时间值(year, month, day, hour, minute, second);
                    }
                }
            }
            return this;
        }

        public 工作表 置单元格双精度值(string regionMark, double value)
        {
            var cell = 取单元格(regionMark, true);
            cell.置双精度值(value);
            return this;
        }

        public 工作表 置单元格双精度值(单元格 cell, double value)
        {
            if (cell != null)
                cell.置双精度值(value);

            return this;
        }

        public 工作表 置区域双精度值(string regionMark, double value, bool autoCreateCell = true)
        {
            return 置区域双精度值(取区域(regionMark), value, autoCreateCell);
        }

        public 工作表 置区域双精度值(区域 region, double value, bool autoCreateCell = true)
        {
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = region.区域体.LastColumn;
            var top = region.区域体.FirstRow;
            var bottom = region.区域体.LastRow;

            for (int i = top; i <= bottom; i++)
            {
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置双精度值(value);
                    }
                }
            }
            return this;
        }

        public 工作表 置单元格公式(string regionMark, string value)
        {
            var cell = 取单元格(regionMark, true);
            cell.置公式(value);
            return this;
        }

        public 工作表 置单元格公式(单元格 cell, string value)
        {
            if (cell != null)
                cell.置公式(value);

            return this;
        }

        public 工作表 置区域公式(string regionMark, string value, bool autoCreateCell = true)
        {
            return 置区域公式(取区域(regionMark), value, autoCreateCell);
        }

        public 工作表 置区域公式(区域 region, string value, bool autoCreateCell = true)
        {
            if (region == null) return this;

            var left = region.区域体.FirstColumn;
            var right = region.区域体.LastColumn;
            var top = region.区域体.FirstRow;
            var bottom = region.区域体.LastRow;

            for (int i = top; i <= bottom; i++)
            {
                for (int j = left; j <= right; j++)
                {
                    var cell = this.取单元格(i, j, autoCreateCell);
                    if (cell != null)
                    {
                        cell.置公式(value);
                    }
                }
            }
            return this;
        }

        /// <summary>
        /// 将 IronPythonList 中的数据粘贴到指定区域。
        /// </summary>
        /// <param name="cellOrRegionMark">区域左上角单元格标记。</param>
        /// <param name="list">二维文字表对象，天然是双层的。</param>
        /// <param name="autoCreateCell">是否自动创建单元格。</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public 工作表 置区域文本值(string cellOrRegionMark, IronPython.Runtime.PythonList list, bool autoCreateCell = true)
        {
            var region = 取区域(cellOrRegionMark);
            单元格 cell;
            if (region == null)
            {
                cell = 取单元格(cellOrRegionMark, autoCreateCell);
            }
            else
            {
                cell = 取单元格(region.区域体.FirstRow, region.区域体.FirstColumn, autoCreateCell);
            }

            if (cell == null)
                throw new Exception("未找到指定的左上角单元格。");

            if (list == null || list.Count <= 0)
                throw new Exception("未提供有效的列表数据。");

            var maxColumnsCount = 0;
            for (int i = 0; i < list.Count; i++)
            {
                var item = list[i];
                if (item == null) continue;

                var listItem = item as PythonList;
                if (listItem == null)
                {
                    // 普通元素，视为文本
                    maxColumnsCount = Math.Max(1, maxColumnsCount);    // 这行就一个元素
                }
                else
                {
                    // 子元素，视为一个数据行
                    if (list.Count > 0)
                    {
                        // 列表非空
                        maxColumnsCount = Math.Max(list.Count, maxColumnsCount);
                    }// else // 此行为空列表，无子元素
                }
            }

            // 此时 maxColumnsCount 即列数
            var left = cell.单元格列号;
            var right = left + maxColumnsCount - 1;
            var top = cell.单元格行号;
            var bottom = top + list.Count - 1;

            for (int i = top; i <= bottom; i++)
            {
                var rowItem = list[i];
                var listRowItem = rowItem as PythonList;
                if (listRowItem == null)
                {
                    // 普通元素，视为文本值
                    var cell2 = this.取单元格(i, left, autoCreateCell);
                    if (cell2 == null)
                        throw new Exception("未能找到对应单元格，指定的索引可能有误！");

                    if (rowItem != null)
                        cell2.置文本值(rowItem.ToString());
                }
                else
                {
                    // 列表子元素，视为一行的集合
                    for (int j = left; j <= right; j++)
                    {
                        var cell2 = this.取单元格(i, j, autoCreateCell);
                        if (cell2 != null)
                        {
                            var index = j - left;
                            if (index >= 0 && index < listRowItem.Count)
                            {
                                var element = listRowItem[j - left];
                                if (element != null)
                                    cell2.置文本值(element.ToString());
                            }
                            //else
                            //{
                            //    cell2.置文本值("");
                            //}
                        }
                    }
                }
            }

            return this;
        }

        public 工作表 置区域文本值(string cellOrRegionMark, 文字表 txtTable, bool autoCreateCell = true)
        {
            var region = 取区域(cellOrRegionMark);
            单元格 cell;
            if (region == null)
            {
                cell = 取单元格(cellOrRegionMark, autoCreateCell);
            }
            else
            {
                cell = 取单元格(region.区域体.FirstRow, region.区域体.FirstColumn, autoCreateCell);
            }

            if (cell == null)
                throw new Exception("未找到指定的左上角单元格。");

            if (txtTable == null || txtTable.文字表行集.Count <= 0)
                throw new Exception("未提供有效的列表数据。");

            var maxColumnsCount = txtTable.最大单元格数;

            var left = cell.单元格列号;
            var right = left + maxColumnsCount - 1;
            var top = cell.单元格行号;
            // var bottom = top + txtTable.文字表行集.Count - 1;

            if (txtTable.文字表标题行 != null)
            {
                var rowItem = txtTable.文字表标题行;
                cell.置文本值(rowItem.文字表单元格集[0].文字表单元格文本);
                this.合并单元格(top, top, left, right);

                if (父工作簿 != null)
                {
                    this.置区域样式(cell.单元格行号, cell.单元格行号, left, right, 父工作簿.淡主标题单元格样式);
                }
                top++;
            }

            if (txtTable.文字表头行集 != null && txtTable.文字表头行集.Count > 0)
            {
                var headTop = top;
                var maxTop = txtTable.文字表头行集.Count + top;
                for (int i = top; i < maxTop; i++)
                {
                    var rowItem = txtTable.文字表头行集[i - headTop];
                    if (rowItem == null)
                    {
                        top++;
                        continue;
                    }

                    for (int j = left; j <= right; j++)
                    {
                        var cell2 = this.取单元格(i, j, autoCreateCell);
                        if (cell2 != null && rowItem.文字表单元格集 != null && rowItem.文字表单元格集.Count > 0)
                        {
                            var index = j - left;
                            if (index >= 0 && index < rowItem.文字表单元格集.Count)
                            {
                                if (rowItem == null) continue;

                                var rowItemCells = rowItem.文字表单元格集[j - left];
                                var cellText = rowItemCells.文字表单元格文本;
                                if (string.IsNullOrWhiteSpace(cellText) == false)
                                    cell2.置文本值(cellText);
                            }
                        }
                    }
                    top++;
                }

                if (父工作簿 != null)
                {
                    this.置区域样式(headTop, maxTop - 1, left, right, 父工作簿.浅微标题单元格样式);
                }
            }

            if (txtTable.文字表体行集 != null && txtTable.文字表体行集.Count > 0)
            {
                var bodyTop = top;
                var maxTop = txtTable.文字表体行集.Count + top;
                for (int i = top; i < maxTop; i++)
                {
                    var rowItem = txtTable.文字表体行集[i - bodyTop];
                    if (rowItem == null)
                    {
                        top++;
                        continue;
                    }

                    for (int j = left; j <= right; j++)
                    {
                        var cell2 = this.取单元格(i, j, autoCreateCell);
                        if (cell2 != null && rowItem.文字表单元格集 != null && rowItem.文字表单元格集.Count > 0)
                        {
                            var index = j - left;
                            if (index >= 0 && index < rowItem.文字表单元格集.Count)
                            {
                                if (rowItem == null) continue;

                                var rowItemCells = rowItem.文字表单元格集[j - left];
                                var cellText = rowItemCells.文字表单元格文本;
                                if (string.IsNullOrWhiteSpace(cellText) == false)
                                    cell2.置文本值(cellText);
                            }
                        }
                    }
                    top++;
                }

                if (父工作簿 != null)
                {
                    this.置区域样式(bodyTop, maxTop - 1, left, right, 父工作簿.较窄单元格样式);
                }
            }

            return this;
        }

        [Obsolete]
        public 工作表 置标签色(色彩标号 color)
        {
            var xsheet = _工作表体 as XSSFSheet;
            if (xsheet != null)
            {
                xsheet.SetTabColor((short)color);
            }
            else
            {
                _工作表体.TabColorIndex = (short)color;
            }

            return this;
        }

        [Obsolete]
        public 工作表 置标签色(单元格色彩标号 color)
        {
            var xsheet = _工作表体 as XSSFSheet;
            if (xsheet != null)
            {
                xsheet.SetTabColor((short)color);
            }
            else
            {
                _工作表体.TabColorIndex = (short)color;
            }

            return this;
        }

        public 工作表 置单元格样式(string cellMark, 单元格样式 cellStyle)
        {
            if (string.IsNullOrWhiteSpace(cellMark))
                return this;

            var reg = new Regex(@"[a-zA-ZＡ-Ｚａ-ｚ]{1,3}[0-9０-９]+");
            if (reg.Match(cellMark).Success == false) return this;

            var rangeText = cellMark + ":" + cellMark;

            return 置区域样式(rangeText, cellStyle);
        }

        public 工作表 置单元格样式(int rowIndex, int columnIndex, 单元格样式 cellStyle)
        {
            return 置区域样式(rowIndex, rowIndex, columnIndex, columnIndex, cellStyle);
        }

        public 工作表 置区域样式(string rangeText, 单元格样式 cellStyle)
        {
            if (string.IsNullOrWhiteSpace(rangeText))
                return this;

            var reg = new Regex(@"[a-zA-ZＡ-Ｚａ-ｚ]{1,3}[0-9０-９]+[:：][a-zA-ZＡ-Ｚａ-ｚ]{1,3}[0-9０-９]+");
            if (reg.Match(rangeText).Success == false) return this;

            var pieces = ChinesePinYin.FatAlphaAndNumbersToThin(rangeText).Split(new char[] { ':', '：' });
            if (pieces.Length != 2) return this;

            var leftTopCellRef = new CellReference(pieces[0]);
            var rightBottomCellRef = new CellReference(pieces[1]);
            var left = leftTopCellRef.Col;
            var top = leftTopCellRef.Row;
            var right = rightBottomCellRef.Col;
            var bottom = rightBottomCellRef.Row;

            for (int i = left; i <= right; i++)
            {
                for (int j = top; j <= bottom; j++)
                {
                    var cell = this.取单元格(j, i);
                    cell.置单元格样式(cellStyle);
                }
            }

            return this;
        }

        public 工作表 置区域样式(区域 range, 单元格样式 cellStyle)
        {
            var left = range.区域体.FirstColumn;
            var top = range.区域体.FirstRow;
            var right = range.区域体.LastColumn;
            var bottom = range.区域体.LastRow;

            for (int i = left; i <= right; i++)
            {
                for (int j = top; j <= bottom; j++)
                {
                    var cell = this.取单元格(j, i);
                    cell.置单元格样式(cellStyle);
                }
            }
            return this;
        }

        public 工作表 置区域样式(int firstRow, int lastRow, int firstColumn, int lastColumn, 单元格样式 cellStyle)
        {
            var left = Math.Min(firstColumn, lastColumn);
            var top = Math.Min(firstRow, lastRow);
            var right = Math.Max(firstColumn, lastColumn);
            var bottom = Math.Max(firstRow, lastRow);

            for (int i = left; i <= right; i++)
            {
                for (int j = top; j <= bottom; j++)
                {
                    var cell = this.取单元格(j, i);
                    cell.置单元格样式(cellStyle);
                }
            }
            return this;
        }

        public string[][] 取值到二维字符串数组(int fstRow, int lastRow, int fstColumn, int lastColumn)
        {
            var fr = Math.Min(fstRow, lastRow);
            var lr = Math.Max(fstRow, lastRow);

            var fc = Math.Min(fstColumn, lastColumn);
            var lc = Math.Max(fstColumn, lastColumn);

            if (fc < 0 || fr < 0) return null;

            string[][] rowsArray = new string[lr - fr + 1][];
            for (int i = fr; i <= lr; i++)
            {
                string[] colsArray = new string[lc - fc + 1];
                for (int j = fc; j <= lc; j++)
                {
                    var cell = 取单元格(i, j);

                    if (cell == null)
                    {
                        colsArray[j - fc] = "";
                    }
                    else
                    {
                        switch (cell.单元格体.CellType)
                        {
                            case CellType.Formula:
                                colsArray[j - fc] = cell.单元格体.CellFormula.ToString(); break;
                            case CellType.Numeric:
                                colsArray[j - fc] = cell.单元格体.NumericCellValue.ToString(); break;
                            case CellType.String:
                                colsArray[j - fc] = cell.单元格体.StringCellValue; break;
                        }
                    }
                }
                rowsArray[i - fr] = colsArray;
            }
            return rowsArray;
        }

        public string[][] 取值到二维字符串数组(string rangeText)
        {
            if (string.IsNullOrWhiteSpace(rangeText))
            {
                try
                {
                    var fstRow = this._工作表体.GetRow(0);
                    if (fstRow == null) return null;

                    var fstRowNum = this._工作表体.FirstRowNum;
                    var lastRowNum = this._工作表体.LastRowNum;
                    return 取值到二维字符串数组(fstRowNum, lastRowNum, fstRow.FirstCellNum, fstRow.LastCellNum);
                }
                catch
                {
                    return null;
                }
            }

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
            if (reg.Match(rangeText).Success == false) return null;

            //try
            //{
            var pieces = rangeText.Split(new char[] { ':', '：' });
            if (pieces.Length != 2) return null;

            var leftTopCellRef = new CellReference(pieces[0]);
            var rightBottomCellRef = new CellReference(pieces[1]);
            return 取值到二维字符串数组(leftTopCellRef.Row, rightBottomCellRef.Row,
                leftTopCellRef.Col, rightBottomCellRef.Col);
            //}
            //catch (Exception ex)
            //{
            //    LMessageBox.ShowWarning(ex.Message);
            //    return null;
            //}
        }

        public string[][] 取二维数组(string rangeText)
        {
            return 取值到二维字符串数组(rangeText);
        }

        public string[][] 到二维数组(string rangeText)
        {
            return 取值到二维字符串数组(rangeText);
        }

        public string[][] 取二维数组(int fstRow, int lastRow, int fstColumn, int lastColumn)
        {
            return 取值到二维字符串数组(fstRow, lastRow, fstColumn, lastColumn);
        }

        public string[][] 到二维数组(int fstRow, int lastRow, int fstColumn, int lastColumn)
        {
            return 取值到二维字符串数组(fstRow, lastRow, fstColumn, lastColumn);
        }

        public 文本数据表 取文字表(string rangeText, bool firstRowIsFieldNames = true)
        {
            var array = 取值到二维字符串数组(rangeText);
            if (array != null && array.Length > 0)
            {
                return new 文本数据表(array, firstRowIsFieldNames);
            }
            return new 文本数据表(取值到二维字符串数组(rangeText), firstRowIsFieldNames);
        }

        public 文本数据表 取文本数据表(string rangeText, bool firstRowIsFieldNames = true)
        {
            return 取文字表(rangeText, firstRowIsFieldNames);
        }

        public static int 列名转索引(string mark)
        {
            try
            {
                var cellr = new CellReference(mark);
                return cellr.Col;
            }
            catch
            {
                return -1;
            }
        }

        public 文本数据表 取文字表(int fstRow, int lastRow, int fstColumn, int lastColumn, int fieldRow)
        {
            if (fieldRow < 0) return null;
            var fieldRows = 取值到二维字符串数组(fieldRow, fieldRow, fstColumn, lastColumn);
            if (fieldRows == null || fieldRows.Length <= 0) return null;

            var array = 取值到二维字符串数组(fstRow, lastRow, fstColumn, lastColumn);
            if (array == null || array.Length <= 0) return null;

            return new 文本数据表(array, fieldRows[0]);
        }

        public 文本数据表 取文本数据表(int fstRow, int lastRow, int fstColumn, int lastColumn, int fieldRow)
        {
            return 取文字表(fstRow, lastRow, fstColumn, lastColumn, fieldRow);
        }

        public 文本数据表 取文字表(int fstRow, int lastRow, int fstColumn, int lastColumn, bool firstRowIsFieldNames = true)
        {
            var array = 取值到二维字符串数组(fstRow, lastRow, fstColumn, lastColumn);
            if (array != null && array.Length > 0)
            {
                return new 文本数据表(array, firstRowIsFieldNames);
            }
            else return null;
        }

        public 文本数据表 取文字表(区域 area, bool firstRowIsFieldNames = true)
        {
            var array = 取值到二维字符串数组(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引);
            if (array != null && array.Length > 0)
            {
                return new 文本数据表(array, firstRowIsFieldNames);
            }
            else return null;
        }

        public 文本数据表 取文本数据表(int fstRow, int lastRow, int fstColumn, int lastColumn, bool firstRowIsFieldNames = true)
        {
            return 取文字表(fstRow, lastRow, fstColumn, lastColumn, firstRowIsFieldNames);
        }

        public 文本数据表 取文本数据表(区域 area, bool firstRowIsFieldNames = true)
        {
            return 取文字表(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引, firstRowIsFieldNames);
        }

        public 文本数据表 到文字表(string rangeText, bool firstRowIsFieldNames = true)
        {
            var array = 取值到二维字符串数组(rangeText);
            if (array != null && array.Length > 0)
            {
                return new 文本数据表(array, firstRowIsFieldNames);
            }
            return new 文本数据表(取值到二维字符串数组(rangeText), firstRowIsFieldNames);
        }

        public 文本数据表 到文本数据表(string rangeText, bool firstRowIsFieldNames = true)
        {
            return 到文字表(rangeText, firstRowIsFieldNames);
        }

        public 文本数据表 到文字表(int fstRow, int lastRow, int fstColumn, int lastColumn, bool firstRowIsFieldNames = true)
        {
            var array = 取值到二维字符串数组(fstRow, lastRow, fstColumn, lastColumn);
            if (array != null && array.Length > 0)
            {
                return new 文本数据表(array, firstRowIsFieldNames);
            }
            else return null;
        }

        public 文本数据表 到文本数据表(int fstRow, int lastRow, int fstColumn, int lastColumn, bool firstRowIsFieldNames = true)
        {
            return 到文字表(fstRow, lastRow, fstColumn, lastColumn, firstRowIsFieldNames);
        }

        public 文本数据表 到文字表(int fstRow, int lastRow, int fstColumn, int lastColumn, int fieldRow)
        {
            return 取文字表(fstRow, lastRow, fstColumn, lastColumn, fieldRow);
        }
        public 文本数据表 到文本数据表(int fstRow, int lastRow, int fstColumn, int lastColumn, int fieldRow)
        {
            return 取文字表(fstRow, lastRow, fstColumn, lastColumn, fieldRow);
        }

        public 文本数据表 到文字表(bool firstRowIsFieldNames = true)
        {
            var array = 到二维数组("");
            return (array == null) ? null : new 文本数据表(array, firstRowIsFieldNames);
        }
        public 文本数据表 到文本数据表(bool firstRowIsFieldNames = true)
        {
            var array = 到二维数组("");
            return (array == null) ? null : new 文本数据表(array, firstRowIsFieldNames);
        }

        public 文本数据行 取文本数据行(int rowIndex, int fstColumn, int lastColumn)
        {
            var fc = Math.Min(fstColumn, lastColumn);
            var lc = Math.Max(fstColumn, lastColumn);

            if (fc < 0 || rowIndex < 0) return null;

            string[] colsArray = new string[lc - fc + 1];
            for (int j = fc; j <= lc; j++)
            {
                var cell = 取单元格(rowIndex, j);

                if (cell == null)
                {
                    colsArray[j] = "";
                }
                else
                {
                    switch (cell.单元格体.CellType)
                    {
                        case CellType.Formula:
                            colsArray[j] = cell.单元格体.CellFormula.ToString(); break;
                        case CellType.Numeric:
                            colsArray[j] = cell.单元格体.NumericCellValue.ToString(); break;
                        case CellType.String:
                            colsArray[j] = cell.单元格体.StringCellValue; break;
                    }
                }
            }
            return new 文本数据行(colsArray);
        }

        public 文本数据行 取文字表行(int rowIndex, int fstColumn, int lastColumn)
        {
            return 取文本数据行(rowIndex, fstColumn, lastColumn);
        }

        private 工作表 CopyRangeToAnotherSheet(CellRangeAddress range, ISheet srcSheet, ISheet destSheet, int rowOffset, int colOffset)
        {
            if (srcSheet == destSheet || destSheet == null) return this;

            // NPOI 有个 Bug: 列宽是整型。所以这里取、置都是8，而 Excel 默认列宽是 8.38 个字符！
            destSheet.DefaultColumnWidth = srcSheet.DefaultColumnWidth;
            destSheet.DefaultRowHeight = srcSheet.DefaultRowHeight;

            var 源工作表 = new 工作表(srcSheet);
            var 目标工作表 = new 工作表(destSheet);

            for (var rowNumber = range.FirstRow; rowNumber <= range.LastRow; rowNumber++)
            {
                IRow sourceRow = srcSheet.GetRow(rowNumber);

                if (destSheet.GetRow(rowNumber + rowOffset) == null)
                    destSheet.CreateRow(rowNumber + rowOffset);
                if (sourceRow != null)
                {
                    IRow destRow = destSheet.GetRow(rowNumber + rowOffset);

                    for (var col = range.FirstColumn; col < sourceRow.LastCellNum && col <= range.LastColumn; col++)
                    {
                        if (rowNumber == range.FirstRow)
                        {
                            // 刷新列宽
                            var srcColWidth = 源工作表.取列宽(col);
                            if (srcColWidth == 2048)
                            {
                                // 解决 NPOI 的Bug: 列宽是整型，所以默认列宽只能是 8，
                                // 而 Excel 默认列宽是 8.38 个字符！
                                srcColWidth = 2304;
                                // 这个2304 是试出来最接近的值，并不是简单的 2048/8 * 8.83 的关系！
                            }
                            目标工作表.置列宽(col + colOffset, srcColWidth, 0);  // 明确指定不添加额外的 0.62 字符宽！
                        }

                        destRow.CreateCell(col + colOffset);
                        单元格.CopyCell(sourceRow.GetCell(col), destRow.GetCell(col + colOffset));
                    }
                }

                var srcRowHeight = 源工作表.取行高(rowNumber);
                if (srcRowHeight >= 0)
                {
                    目标工作表.置行高(rowNumber + rowOffset, srcRowHeight);
                }
            }

            foreach (var mr in srcSheet.MergedRegions)
            {
                if (mr.Intersects(range) == false) continue;

                destSheet.AddMergedRegion(new CellRangeAddress(mr.FirstRow + rowOffset, mr.LastRow + rowOffset, mr.FirstColumn + colOffset, mr.LastColumn + colOffset));
            }

            return this;
        }

        public 工作表 复制区域到其它表(int firstRow, int lastRow, int firstColumn, int lastColumn,
            工作表 destSheet, int rowOffset = 0, int colOffset = 0)
        {
            if (destSheet == this || destSheet == null) return this;

            int fr = firstRow, lr = lastRow, fc = firstColumn, lc = lastColumn;
            firstRow = Math.Min(fr, lr); lastRow = Math.Max(fr, lr);
            firstColumn = Math.Min(fc, lc); lastColumn = Math.Max(fc, lc);

            return CopyRangeToAnotherSheet(
                new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn),
                this._工作表体, destSheet.工作表体, rowOffset, colOffset);
        }

        public 工作表 复制区域到其它表(int firstRow, int lastRow, int firstColumn, int lastColumn,
            ISheet destSheet = null, int rowOffset = 0, int colOffset = 0)
        {
            if (destSheet == this || destSheet == null) return this;

            int fr = firstRow, lr = lastRow, fc = firstColumn, lc = lastColumn;
            firstRow = Math.Min(fr, lr); lastRow = Math.Max(fr, lr);
            firstColumn = Math.Min(fc, lc); lastColumn = Math.Max(fc, lc);

            return CopyRangeToAnotherSheet(
                new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn),
                this._工作表体, destSheet, rowOffset, colOffset);
        }

        public 工作表 复制区域到其他表(int firstRow, int lastRow, int firstColumn, int lastColumn,
            工作表 destSheet, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其它表(firstRow, lastRow, firstColumn, lastColumn, destSheet, rowOffset, colOffset);
        }

        public 工作表 复制区域到其他表(int firstRow, int lastRow, int firstColumn, int lastColumn,
            ISheet destSheet = null, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其它表(firstRow, lastRow, firstColumn, lastColumn, destSheet, rowOffset, colOffset);
        }

        public 工作表 复制区域到其它表(区域 area, 工作表 destSheet, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其它表(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引, destSheet, rowOffset, colOffset);
        }
        public 工作表 复制区域到其它表(区域 area, ISheet destSheet, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其它表(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引, destSheet, rowOffset, colOffset);
        }
        public 工作表 复制区域到其他表(区域 area, 工作表 destSheet, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其他表(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引, destSheet, rowOffset, colOffset);
        }
        public 工作表 复制区域到其他表(区域 area, ISheet destSheet, int rowOffset = 0, int colOffset = 0)
        {
            return 复制区域到其他表(area.首行索引, area.尾行索引, area.首列索引, area.尾列索引, destSheet, rowOffset, colOffset);
        }

        private 工作表 CopyColumnToAnotherSheet(string colMark, ISheet sourceSheet, ISheet destSheet)
        {
            if (sourceSheet == destSheet || destSheet == null) return this;

            int colNumber = CellReference.ConvertColStringToIndex(colMark);
            var range = new CellRangeAddress(0, sourceSheet.LastRowNum, colNumber, colNumber);
            return CopyRangeToAnotherSheet(range, sourceSheet, destSheet, 0, 0);
        }

        public 工作表 复制列到其它表(string colNum, ISheet destSheet)
        {
            return CopyColumnToAnotherSheet(colNum, this.工作表体, destSheet);
        }

        public 工作表 复制列到其它表(int colNum, ISheet destSheet)
        {
            var range = new CellRangeAddress(0, this.工作表体.LastRowNum, colNum, colNum);
            return CopyRangeToAnotherSheet(range, this.工作表体, destSheet, 0, 0);
        }

        public 工作表 复制列到其它表(string colNum, 工作表 destSheet)
        {
            return CopyColumnToAnotherSheet(colNum, this.工作表体, destSheet.工作表体);
        }

        public 工作表 复制列到其它表(int colNum, 工作表 destSheet)
        {
            var range = new CellRangeAddress(0, this.工作表体.LastRowNum, colNum, colNum);
            return CopyRangeToAnotherSheet(range, this.工作表体, destSheet.工作表体, 0, 0);
        }


        public 工作表 复制列到其他表(string colNum, ISheet destSheet)
        {
            return CopyColumnToAnotherSheet(colNum, this.工作表体, destSheet);
        }

        public 工作表 复制列到其他表(int colNum, ISheet destSheet)
        {
            var range = new CellRangeAddress(0, this.工作表体.LastRowNum, colNum, colNum);
            return CopyRangeToAnotherSheet(range, this.工作表体, destSheet, 0, 0);
        }

        public 工作表 复制列到其他表(string colNum, 工作表 destSheet)
        {
            return CopyColumnToAnotherSheet(colNum, this.工作表体, destSheet.工作表体);
        }

        public 工作表 复制列到其他表(int colNum, 工作表 destSheet)
        {
            var range = new CellRangeAddress(0, this.工作表体.LastRowNum, colNum, colNum);
            return CopyRangeToAnotherSheet(range, this.工作表体, destSheet.工作表体, 0, 0);
        }


        public 工作表 合并单元格(int fstRow, int lstRow, int fstCol, int lstCol, 单元格样式 style = null)
        {
            var area = new 区域(fstRow, lstRow, fstCol, lstCol);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return this;
        }

        public 工作表 合并单元格(string regionMark, 单元格样式 style = null)
        {
            var range = CellRangeAddress.ValueOf(regionMark);
            var area = new 区域(range.FirstRow, range.LastRow, range.FirstColumn, range.LastColumn);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return this;
        }

        public 单元格 取合并单元格(int fstRow, int lstRow, int fstCol, int lstCol, 单元格样式 style = null)
        {
            var area = new 区域(fstRow, lstRow, fstCol, lstCol);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return 取单元格(fstRow, fstCol, true);
        }

        public 单元格 获取合并单元格(int fstRow, int lstRow, int fstCol, int lstCol, 单元格样式 style = null)
        {
            var area = new 区域(fstRow, lstRow, fstCol, lstCol);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return 取单元格(fstRow, fstCol, true);
        }

        public 单元格 取合并单元格(string regionMark, 单元格样式 style = null)
        {
            var range = CellRangeAddress.ValueOf(regionMark);
            var area = new 区域(range.FirstRow, range.LastRow, range.FirstColumn, range.LastColumn);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return 取单元格(range.FirstRow, range.FirstColumn);
        }

        public 单元格 获取合并单元格(string regionMark, 单元格样式 style = null)
        {
            var range = CellRangeAddress.ValueOf(regionMark);
            var area = new 区域(range.FirstRow, range.LastRow, range.FirstColumn, range.LastColumn);
            if (style != null)
            {
                this.置区域样式(area, style);  // 先置样式再合并
            }
            _工作表体.AddMergedRegion(area.区域体);
            return 取单元格(range.FirstRow, range.FirstColumn);
        }

        /// <summary>
        /// 置列宽。
        /// </summary>
        /// <param name="index">列索引，从0开始算。</param>
        /// <param name="width">列宽度单位是 1/256 个字符宽度，与字体相关，无法通过常规单位精确控制！！</param>
        public 工作表 置列宽(int index, double width, int? offset = null)
        {
            if (offset != null && offset.HasValue)
            {
                _工作表体.SetColumnWidth(index, width + offset.Value);
            }
            else
            {
                _工作表体.SetColumnWidth(index, width + 159);
            }
            return this;
        }

        public double 取像素列宽(int index)
        {
            return _工作表体.GetColumnWidthInPixels(index);
        }

        public 工作表 置字符列宽(int index, double count, double offset = 0.62)
        {
            var width = (count + offset) * 256;
            _工作表体.SetColumnWidth(index, (int)width + 1);
            return this;
        }

        public 工作表 置自动列宽(int colIndex)
        {
            _工作表体.AutoSizeColumn(colIndex);
            return this;
        }

        public 工作表 置自适应列宽(int colIndex)
        {
            _工作表体.AutoSizeColumn(colIndex);
            return this;
        }

        public 工作表 置自动行高(int rowIndex)
        {
            _工作表体.AutoSizeRow(rowIndex);
            return this;
        }

        public 工作表 置自适应行高(int rowIndex)
        {
            _工作表体.AutoSizeRow(rowIndex);
            return this;
        }

        /// <summary>
        /// 置行高。
        /// </summary>
        /// <param name="index">行索引。</param>
        /// <param name="height">行高单位是 1/20 个点（磅），即 twips（缇）。（HeightInPoints 单位是点）</param>
        public 工作表 置行高(int index, int height)
        {
            var row = 取行(index);
            row.置行高((short)height);
            return this;
        }

        public 工作表 置厘米行高(int index, double cm)
        {
            var row = 取行(index);
            row.置厘米行高(cm);
            return this;
        }

        public 工作表 置毫米行高(int index, double mm)
        {
            var row = 取行(index);
            row.置毫米行高(mm);

            return this;
        }

        public 工作表 置点行高(int index, double p)
        {
            var row = 取行(index);
            row.置点行高((short)p);

            return this;
        }

        public 工作表 置磅行高(int index, double p)
        {
            var row = 取行(index);
            row.置磅行高((short)p);

            return this;
        }

        /// <summary>
        /// 和“置行高”相同。（默认以 缇（1/1440 英寸） 为单位。）
        /// </summary>
        /// <param name="index"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public 工作表 置缇行高(int index, int height)
        {
            var row = 取行(index);
            row.置行高((short)height);

            return this;
        }

        public int 取行高(int rowIndex)
        {
            var row = _工作表体.GetRow(rowIndex);
            if (row == null) return -1;

            return row.Height;
        }

        /// <summary>
        /// 1 厘米 = 567 缇
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <returns></returns>
        public double 取行高厘米数(int rowIndex)
        {
            var h = 取行高(rowIndex);
            if (h <= 0) return 0;

            return (double)(h / 567);
        }

        public double 取厘米行高(int rowIndex)
        {
            return 取行高厘米数(rowIndex);
        }

        /// <summary>
        /// 1 毫米 = 56.7 缇
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <returns></returns>
        public double 取行高毫米数(int rowIndex)
        {
            var h = 取行高(rowIndex);
            if (h <= 0) return 0;

            return (double)(h / 56.7);
        }

        public double 取毫米行高(int rowIndex)
        {
            return 取行高毫米数(rowIndex);
        }

        /// <summary>
        /// 1 磅 = 1 点 = 20 twips（缇）
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <returns></returns>
        public double 取行高磅数(int rowIndex)
        {
            var h = 取行高(rowIndex);
            if (h <= 0) return 0;

            return (double)(h / 20);
        }

        public double 取磅行高(int rowIndex)
        {
            return 取行高磅数(rowIndex);
        }

        /// <summary>
        /// Point = 20 twips
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <returns></returns>
        public double 取行高点数(int rowIndex)
        {
            var h = 取行高(rowIndex);
            if (h <= 0) return 0;

            return (double)(h / 20);
        }

        public double 取点行高(int rowIndex)
        {
            return 取行高点数(rowIndex);
        }

        public int 取行高缇数(int rowIndex)
        {
            return 取行高(rowIndex);
        }

        public int 取缇行高(int rowIndex)
        {
            return 取行高(rowIndex);
        }

        public double 取列宽(int colIndex)
        {
            return _工作表体.GetColumnWidth(colIndex);
        }

        public double 取列宽字符数(int colIndex)
        {
            var w = _工作表体.GetColumnWidth(colIndex);

            if (w <= 0) return 0;

            return w / 256;
        }

        /// <summary>
        /// 置表格默认列宽。
        /// </summary>
        /// <param name="width">单位是 1/256 个字符。</param>
        public 工作表 置默认列宽(int width)
        {
            _工作表体.DefaultColumnWidth = width;
            return this;
        }

        public 工作表 置默认字符列宽(int width)
        {
            _工作表体.DefaultColumnWidth = width * 256;
            return this;
        }

        /// <summary>
        /// 置表格默认行高。
        /// </summary>
        /// <param name="height">单位是 1/20 个点。</param>
        public 工作表 置默认行高(int height)
        {
            _工作表体.DefaultRowHeight = (short)height;
            return this;
        }

        public 工作表 置默认厘米行高(double cm)
        {
            _工作表体.DefaultRowHeight = (short)(cm * 567);
            return this;
        }

        public 工作表 置默认毫米行高(double mm)
        {
            _工作表体.DefaultRowHeight = (short)(mm * 56.7);
            return this;
        }

        public 工作表 置默认点行高(int p)
        {
            _工作表体.DefaultRowHeight = (short)(p * 20);
            return this;
        }

        public 工作表 置默认磅行高(int p)
        {
            _工作表体.DefaultRowHeight = (short)(p * 20);
            return this;
        }

        public 工作表 置默认缇行高(int p)
        {
            _工作表体.DefaultRowHeight = (short)p;
            return this;
        }

        public 工作表 置列默认样式(int colIndex, 单元格样式 newStyle)
        {
            _工作表体.SetDefaultColumnStyle(colIndex, newStyle.样式);
            return this;
        }

        public 工作表 插入分页符(int rowIndex)
        {
            _工作表体.SetRowBreak(rowIndex);
            return this;
        }

        public 工作表 置方向(string orient)
        {
            if (string.IsNullOrWhiteSpace(orient))
            {
                orient = "h";
            }

            switch (orient.ToLower())
            {
                case "v":
                case "vertical":
                case "纵":
                case "纵向":
                    {
                        _工作表体.PrintSetup.Landscape = false;
                        break;
                    }
                default:
                    {
                        _工作表体.PrintSetup.Landscape = true;
                        break;
                    }
            }
            return this;
        }

        public string 取方向()
        {
            if (_工作表体.PrintSetup.Landscape)
                return "horizontal";

            return "vertical";
        }

        public string 取纸张方向()
        {
            if (_工作表体.PrintSetup.Landscape)
                return "horizontal";

            return "vertical";
        }

        public 工作表 置页面方向(string orient)
        {
            return 置方向(orient);
        }

        public 工作表 置纸张方向(string orient)
        {
            return 置方向(orient);
        }

        public 工作表 置纸型(int paperSize)
        {
            _工作表体.PrintSetup.PaperSize = (short)paperSize;
            return this;
        }

        /// <summary>
        /// 此方法使用的枚举很多纸型在 Excel/WpsOffice 中显示不出来！
        /// </summary>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public 工作表 置纸型(工作表页面尺寸 newValue)
        {
            _工作表体.PrintSetup.PaperSize = (short)newValue;
            return this;
        }

        public 工作表 置纸张类型(纸张类型 newValue)
        {
            _工作表体.PrintSetup.PaperSize = (short)newValue;
            return this;
        }

        public string 取纸张类型名称()
        {
            return GetExcelPaperSizeNam(_工作表体.PrintSetup.PaperSize);
        }

        private string GetExcelPaperSizeNam(int paperID)
        {
            var papers = @"1,US Letter, 8 1/2 x 11 in
2,US Letter, Small 8 1/2 x 11 in
3,US Tabloid, 11 x 17 in
4,US Ledger ,17 x 11 in
5,US Legal, 8 1/2 x 14 in
6,US Statement, 5 1/2 x 8 1/2 in
7,US Executive, 7 1/4 x 10 1/2 in
8,A3, 297 x 420 mm
9,A4, 210 x 297 mm
10,A4, Small 210 x 297 mm
11,A5, 148 x 210 mm
12,B4 (JIS), 250 x 354
13,B5 (JIS), 182 x 257 mm
14,Folio ,8 1/2 x 13 in
15,Quarto, 215 x 275 mm
16,i1014, 10 x 14 in
17,i1117, 11 x 17 in
18,US Note, 8 1/2 x 11 in
19,US Envelope #9, 3 7/8 x 8 7/8
20,US Envelope #10, 4 1/8 x 9 1/2
21,US Envelope #11, 4 1/2 x 10 3/8
22,US Envelope #12, 4 \276 x 11
23,US Envelope #14, 5 x 11 1/2
24,C size sheet,
25,D size sheet,
26,E size sheet,
27,Envelope DL ,110 x 220mm
28,Envelope C5 ,162 x 229 mm
29,Envelope C3 ,324 x 458 mm
30,Envelope C4 ,229 x 324 mm
31,Envelope C6 ,114 x 162 mm
32,Envelope C65 ,114 x 229 mm
33,Envelope B4 ,250 x 353 mm
34,Envelope B5 ,176 x 250 mm
35,Envelope B6 ,176 x 125 mm
36,Envelope ,110 x 230 mm
37,US Envelope Monarch, 3.875 x 7.5 in
38,6 3/4 US Envelope ,3 5/8 x 6 1/2 in
39,US Std Fanfold ,14 7/8 x 11 in
40,German Std Fanfold ,8 1/2 x 12 in
41,German Legal Fanfold, 8 1/2 x 13 in
42,B4 (ISO) ,250 x 353 mm
43,Japanese Postcard ,100 x 148 mm
44,i0911, 9 x 11 in
45,i1011, 10 x 11 in
46,i1511, 15 x 11 in
47,Envelope Invite, 220 x 220 mm
48,RESERVED–DO NOT USE,
49,RESERVED–DO NOT USE,
50,US Letter Extra ,9 \275 x 12 in
51,US Legal Extra ,9 \275 x 15 in
52,US Tabloid Extra ,11.69 x 18 in
53,A4 Extra ,9.27 x 12.69 in
54,Letter Transverse, 8 \275 x 11 in
55,A4 Transverse ,210 x 297 mm
56,Letter Extra Transverse ,9 \275 x 12 in
57,SuperA/SuperA/A4 ,227 x 356 mm
58,SuperB/SuperB/A3 ,305 x 487 mm
59,US Letter Plus ,8.5 x 12.69 in
60,A4 Plus ,210 x 330 mm
61,A5 Transverse ,148 x 210 mm
62,B5 (JIS) Transverse ,182 x 257 mm
63,A3 Extra ,322 x 445 mm
64,A5 Extra ,174 x 235 mm
65,B5 (ISO), Extra 201 x 276 mm
66,A2 ,420 x 594 mm
67,A3 Transverse ,297 x 420 mm
68,A3 Extra Transverse ,322 x 445 mm
69,Japanese Double Postcard ,200 x 148 mm
70,A6 ,105 x 148 mm
71,Japanese Envelope Kaku #2,
72,Japanese Envelope Kaku #3,
73,Japanese Envelope Chou #3,
74,Japanese Envelope Chou #4,
75,Letter Rotated ,11 x 8 1/2 11 in
76,A3 Rotated ,420 x 297 mm
77,A4 Rotated, 297 x 210 mm
78,A5 Rotated ,210 x 148 mm
79,B4 (JIS) Rotated ,364 x 257 mm
80,B5 (JIS) Rotated ,257 x 182 mm
81,Japanese Postcard Rotated ,148 x 100 mm
82,Double Japanese Postcard Rotated ,148 x 200 mm
83,A6 Rotated ,148 x 105 mm
84,Japanese Envelope Kaku #2, Rotated
85,Japanese Envelope Kaku #3, Rotated
86,Japanese Envelope Chou #3, Rotated
87,Japanese Envelope Chou #4, Rotated
88,B6 (JIS) ,128 x 182 mm
89,B6 (JIS) ,Rotated 182 x 128 mm
90,i1211, 12 x 11 in
91,Japanese Envelope You #4,
92,Japanese Envelope You #4 Rotated,
93,PRC 16K ,146 x 215 mm
94,PRC 32K ,97 x 151 mm
95,PRC 32K(Big) ,97 x 151 mm
96,PRC Envelope #1 ,102 x 165 mm
97,PRC Envelope #2 ,102 x 176 mm
98,PRC Envelope #3, 125 x 176 mm
99,PRC Envelope #4 ,110 x 208 mm
100,PRC Envelope #5 ,110 x 220 mm
101,PRC Envelope #6 ,120 x 230 mm
102,PRC Envelope #7 ,160 x 230 mm
103,PRC Envelope #8 ,120 x 309 mm
104,PRC Envelope #9 ,229 x 324 mm
105,PRC Envelope #10 ,324 x 458 mm
106,PRC 16K Rotated,
107,PRC 32K Rotated,
108,PRC 32K(Big) Rotated,
109,PRC Envelope #1 Rotated ,165 x 102 mm
110,PRC Envelope #2 Rotated ,176 x 102 mm
111,PRC Envelope #3 Rotated ,176 x 125 mm
112,PRC Envelope #4 Rotated ,208 x 110 mm
113,PRC Envelope #5 Rotated ,220 x 110 mm
114,PRC Envelope #6 Rotated ,230 x 120 mm
115,PRC Envelope #7 Rotated ,230 x 160 mm
116,PRC Envelope #8 Rotated ,309 x 120 mm
117,PRC Envelope #9 Rotated ,324 x 229 mm
118,PRC Envelope #10 Rotated ,458 x 324 mm
";
            var lines = papers.Split(new char[] { '\r', '\n', }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var line in lines)
            {
                var spans = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (spans.Length >= 2)
                {
                    if (paperID.ToString().ToLower() == spans[0].Trim().ToLower())
                    {
                        return spans[1].Trim();
                    }
                }
            }

            return "UnKnown PaperSize";
        }

        public 工作表 置顶端标题行(int firstRow, int lastRow, int fstColumn, int lastColumn)
        {
            _工作表体.RepeatingRows = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置顶端标题区域(区域 range)
        {
            int firstRow = range.区域体.FirstRow;
            int lastRow = range.区域体.LastRow;
            int fstColumn = range.区域体.FirstColumn;
            int lastColumn = range.区域体.LastColumn;
            _工作表体.RepeatingRows = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置顶端标题区域(string rangeMark)
        {
            if (string.IsNullOrEmpty(rangeMark))
            {
                LMessageBox.ShowWarning("未指定模板区域。");
                return this;
            }

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
            rangeMark = rangeMark.Replace("：", ":");
            if (reg.Match(rangeMark).Success == false)
            {
                LMessageBox.Show("模板区域字符串标记不合法！");
                return this;
            }

            var range = CellRangeAddress.ValueOf(rangeMark);

            int firstRow = range.FirstRow;
            int lastRow = range.LastRow;
            int fstColumn = range.FirstColumn;
            int lastColumn = range.LastColumn;
            _工作表体.RepeatingRows = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置左侧标题列(int firstRow, int lastRow, int fstColumn, int lastColumn)
        {
            _工作表体.RepeatingColumns = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置左侧标题区域(区域 range)
        {
            int firstRow = range.区域体.FirstRow;
            int lastRow = range.区域体.LastRow;
            int fstColumn = range.区域体.FirstColumn;
            int lastColumn = range.区域体.LastColumn;
            _工作表体.RepeatingColumns = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置左侧标题区域(string rangeMark)
        {
            if (string.IsNullOrEmpty(rangeMark))
            {
                LMessageBox.ShowWarning("未指定模板区域。");
                return this;
            }

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
            rangeMark = rangeMark.Replace("：", ":");
            if (reg.Match(rangeMark).Success == false)
            {
                LMessageBox.Show("模板区域字符串标记不合法！");
                return this;
            }

            var range = CellRangeAddress.ValueOf(rangeMark);

            int firstRow = range.FirstRow;
            int lastRow = range.LastRow;
            int fstColumn = range.FirstColumn;
            int lastColumn = range.LastColumn;
            _工作表体.RepeatingColumns = new CellRangeAddress(firstRow, lastRow, fstColumn, lastColumn);
            return this;
        }

        public 工作表 置打印顺序(打印顺序 order)
        {
            switch (order)
            {
                case 打印顺序.先列后行:
                    _工作表体.PrintSetup.LeftToRight = false;
                    break;
                case 打印顺序.先行后列:
                default:
                    _工作表体.PrintSetup.LeftToRight = true;
                    break;
            }
            return this;
        }

        public 工作表 置起始页码(short i)
        {
            if (i > 0)
            {
                _工作表体.PrintSetup.UsePage = true;
                _工作表体.PrintSetup.PageStart = i;
            }
            else
            {
                _工作表体.PrintSetup.UsePage = false;
            }
            return this;
        }

        public 工作表 置单色打印(bool singleColor = true)
        {
            _工作表体.PrintSetup.NoColor = singleColor;
            return this;
        }

        public 工作表 置草稿品质(bool isDraft = true)
        {
            _工作表体.PrintSetup.Draft = isDraft;
            return this;
        }

        public 工作表 置打印批注(bool printNotes = true)
        {
            _工作表体.PrintSetup.Notes = printNotes;
            return this;
        }

        public 工作表 置尾部打印批注(bool printNotesAtEnd = true)
        {
            _工作表体.PrintSetup.EndNote = printNotesAtEnd;
            return this;
        }

        public 工作表 置错误打印模式(错误打印模式 errPrintMode)
        {
            switch (errPrintMode)
            {
                case 错误打印模式.错误直接显示:
                    _工作表体.PrintSetup.CellError = DisplayCellErrorType.ErrorDisplayOnSheet;
                    break;
                case 错误打印模式.错误显示为空白:
                    _工作表体.PrintSetup.CellError = DisplayCellErrorType.ErrorAsBlank;
                    break;
                case 错误打印模式.错误显示为划线:
                    _工作表体.PrintSetup.CellError = DisplayCellErrorType.ErrorAsDashes;
                    break;
                case 错误打印模式.错误显示为NA:
                default:
                    _工作表体.PrintSetup.CellError = DisplayCellErrorType.ErrorAsNA;
                    break;
            }
            return this;
        }

        public 工作表 置打印网格线(bool printGridLine = true)
        {
            _工作表体.IsPrintGridlines = printGridLine;
            return this;
        }

        public 工作表 置打印行列标头(bool printHeaders = true)
        {
            _工作表体.IsPrintRowAndColumnHeadings = printHeaders;
            return this;
        }

        public 工作表 置打印区域(int fstRow, int lastRow, int fstColumn, int lastColumn)
        {
            if (_工作表体.Workbook != null)
            {
                var wb = _工作表体.Workbook;
                wb.SetPrintArea(wb.GetSheetIndex(_工作表体), fstColumn, lastColumn, fstRow, lastRow);
            }
            return this;
        }

        public 工作表 置打印区域(区域 range)
        {
            if (_工作表体.Workbook != null)
            {
                int fstRow = range.区域体.FirstRow;
                int lastRow = range.区域体.LastRow;
                int fstColumn = range.区域体.FirstColumn;
                int lastColumn = range.区域体.LastColumn;
                var wb = _工作表体.Workbook;
                wb.SetPrintArea(wb.GetSheetIndex(_工作表体), fstColumn, lastColumn, fstRow, lastRow);
            }
            return this;
        }

        public 工作表 置打印区域(string rangeMark)
        {
            if (_工作表体.Workbook != null)
            {
                if (string.IsNullOrEmpty(rangeMark))
                {
                    LMessageBox.ShowWarning("未指定模板区域。");
                    return this;
                }

                var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
                rangeMark = rangeMark.Replace("：", ":");
                if (reg.Match(rangeMark).Success == false)
                {
                    LMessageBox.Show("模板区域字符串标记不合法！");
                    return this;
                }

                var range = CellRangeAddress.ValueOf(rangeMark);

                int fstRow = range.FirstRow;
                int lastRow = range.LastRow;
                int fstColumn = range.FirstColumn;
                int lastColumn = range.LastColumn;
                var wb = _工作表体.Workbook;
                wb.SetPrintArea(wb.GetSheetIndex(_工作表体), fstColumn, lastColumn, fstRow, lastRow);
            }
            return this;
        }

        public 工作表 置工作表纸张类型(纸张类型 newPaper)
        {
            return 置纸张类型(newPaper);
        }

        public 工作表 置缩放百分比(short num = 100)
        {
            if (num < 0) num = 0;
            if (num > 100) num = 100;

            _工作表体.PrintSetup.Scale = num;
            return this;
        }

        public 工作表 置页宽缩放倍数(short times = 1)
        {
            if (times < 1) times = 1;
            _工作表体.PrintSetup.FitWidth = times;
            return this;
        }

        public 工作表 置页高缩放倍数(short times = 1)
        {
            if (times < 1) times = 1;
            _工作表体.PrintSetup.FitHeight = times;
            return this;
        }

        public 工作表 缩放到单页()
        {
            _工作表体.FitToPage = true;
            _工作表体.PrintSetup.FitWidth = 1;
            _工作表体.PrintSetup.FitHeight = 1;
            _工作表体.Autobreaks = true;
            return this;
        }

        public 工作表 缩放所有列到单页()
        {
            _工作表体.FitToPage = true;
            _工作表体.PrintSetup.FitWidth = 1;
            _工作表体.PrintSetup.FitHeight = 0;
            _工作表体.Autobreaks = true;
            return this;
        }

        public 工作表 缩放所有行到单页()
        {
            _工作表体.FitToPage = true;
            _工作表体.PrintSetup.FitWidth = 0;
            _工作表体.PrintSetup.FitHeight = 1;
            _工作表体.Autobreaks = true;
            return this;
        }

        public 工作表 取消行列缩放()
        {
            _工作表体.FitToPage = false;
            _工作表体.PrintSetup.FitWidth = 0;
            _工作表体.PrintSetup.FitHeight = 0;
            _工作表体.Autobreaks = true;
            return this;
        }

        public 工作表 置页面水平居中(bool isAlignCenter = true)
        {
            _工作表体.HorizontallyCenter = isAlignCenter;
            return this;
        }

        public 工作表 置页面垂直居中(bool isAlignCenter = true)
        {
            _工作表体.VerticallyCenter = isAlignCenter;
            return this;
        }

        /// <summary>
        /// 设置工作表页面左、上、右、下四边边距。
        /// </summary>
        /// <param name="left">左边距，单位厘米</param>
        /// <param name="top">上边距，单位厘米</param>
        /// <param name="right">右边距，单位厘米</param>
        /// <param name="bottom">下边距，单位厘米</param>
        public 工作表 置页边距(double left, double top, double right, double bottom)
        {
            _工作表体.SetMargin(MarginType.LeftMargin, left / 2.54);   // 此方法默认单位是英寸
            _工作表体.SetMargin(MarginType.TopMargin, top / 2.54);
            _工作表体.SetMargin(MarginType.RightMargin, right / 2.54);
            _工作表体.SetMargin(MarginType.BottomMargin, bottom / 2.54);
            return this;
        }

        public IronPython.Runtime.PythonList 英寸页边距列表
        {
            get
            {
                var list = new IronPython.Runtime.PythonList();
                list.Add(_工作表体.GetMargin(MarginType.LeftMargin));
                list.Add(_工作表体.GetMargin(MarginType.TopMargin));
                list.Add(_工作表体.GetMargin(MarginType.RightMargin));
                list.Add(_工作表体.GetMargin(MarginType.BottomMargin));
                list.Add(_工作表体.PrintSetup.HeaderMargin);
                list.Add(_工作表体.PrintSetup.FooterMargin);
                return list;
            }
        }

        /// <summary>
        /// 设置工作表页眉边距、页脚边距。
        /// </summary>
        /// <param name="headerMargin">页眉边距，单位为厘米。</param>
        /// <param name="footerMargin">页脚边距，单位为厘米。</param>
        public 工作表 置页眉页脚边距(double headerMargin, double footerMargin)
        {
            _工作表体.PrintSetup.HeaderMargin = headerMargin / 2.54;  // 1厘米≈28.35磅 1英寸=72磅
            _工作表体.PrintSetup.FooterMargin = footerMargin / 2.54;  // 这里用的单位是英寸
            return this;
        }

        public 工作表 置页眉边距(double margin)
        {
            _工作表体.PrintSetup.HeaderMargin = margin / 2.54;  // 1厘米≈28.35磅 1英寸=72磅
            return this;
        }

        public double 取页眉边距()
        {
            return _工作表体.PrintSetup.HeaderMargin * 2.54;  // 这里用的单位是英寸
        }

        public 工作表 置页脚边距(double margin)
        {
            _工作表体.PrintSetup.FooterMargin = margin / 2.54;  // 这里用的单位是英寸
            return this;
        }

        public double 取页脚边距()
        {
            return _工作表体.PrintSetup.FooterMargin * 2.54;  // 这里用的单位是英寸
        }

        public 工作表 插入页眉(string pageHeaderText, string align = "left")
        {
            if (string.IsNullOrWhiteSpace(pageHeaderText)) return this;
            if (string.IsNullOrWhiteSpace(align))
                align = "left";

            switch (align.ToLower())
            {
                case "l":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        _工作表体.Header.Left = pageHeaderText;
                        break;
                    }
                case "r":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        _工作表体.Header.Right = pageHeaderText;
                        break;
                    }
                default:
                    {
                        _工作表体.Header.Center = pageHeaderText;
                        break;
                    }
            }
            return this;
        }

        public 工作表 插入页脚(string pageFooterText, string align = "right")
        {
            if (string.IsNullOrWhiteSpace(pageFooterText)) return this;
            if (string.IsNullOrWhiteSpace(align))
                align = "left";

            switch (align.ToLower())
            {
                case "l":
                case "left":
                case "左":
                case "左齐":
                case "左对齐":
                    {
                        _工作表体.Footer.Left = pageFooterText;
                        break;
                    }
                case "r":
                case "right":
                case "右":
                case "右齐":
                case "右对齐":
                    {
                        _工作表体.Footer.Right = pageFooterText;
                        break;
                    }
                default:
                    {
                        _工作表体.Footer.Center = pageFooterText;
                        break;
                    }
            }
            return this;
        }

        public bool 是否打印网格线
        {
            get { return _工作表体.DisplayGridlines; }
            set { _工作表体.DisplayGridlines = value; }
        }

        public bool 是否显示网格线
        {
            get { return _工作表体.DisplayGridlines; }
            set { _工作表体.DisplayGridlines = value; }
        }

        public bool 是否打印公式
        {
            get { return _工作表体.DisplayFormulas; }
            set { _工作表体.DisplayFormulas = value; }
        }

        public bool 是否显示公式
        {
            get { return _工作表体.DisplayFormulas; }
            set { _工作表体.DisplayFormulas = value; }
        }

        public bool 是否打印行列标头
        {
            get { return _工作表体.DisplayRowColHeadings; }
            set { _工作表体.DisplayRowColHeadings = value; }
        }

        public bool 是否显示行列标头
        {
            get { return _工作表体.DisplayRowColHeadings; }
            set { _工作表体.DisplayRowColHeadings = value; }
        }

        public bool 是否打印零值
        {
            get { return _工作表体.DisplayZeros; }
            set { _工作表体.DisplayZeros = value; }
        }

        public bool 是否显示零值
        {
            get { return _工作表体.DisplayZeros; }
            set { _工作表体.DisplayZeros = value; }
        }
    }

    public class 文本数据行
    {
        public 文本数据行(string[] dataArray)
        {
            _数据数组 = dataArray;
        }

        public 文本数据行(IronPython.Runtime.PythonList dataList)
        {
            var dataArray = new string[dataList.Count];
            for (int i = 0; i < dataList.Count; i++)
            {
                dataArray[i] = dataList[i].ToString();
            }
            _数据数组 = dataArray;
        }

        public 文本数据行(IronPython.Runtime.PythonTuple dataTuple)
        {
            var dataArray = new string[dataTuple.Count];
            for (int i = 0; i < dataTuple.Count; i++)
            {
                dataArray[i] = dataTuple[i].ToString();
            }
            _数据数组 = dataArray;
        }

        private 文本数据表 _宿主数据表 = null;

        public 文本数据表 宿主数据表
        {
            get { return _宿主数据表; }
            set { _宿主数据表 = value; }
        }

        private string[] _数据数组;

        public string[] 数据数组
        {
            get { return _数据数组; }
        }

        public PythonTuple 数据元组
        {
            get
            {
                if (_数据数组 == null) return null;
                return new PythonTuple(_数据数组);
            }
        }

        public PythonList 数据列表
        {
            get
            {
                if (_数据数组 == null) return null;
                var list = new PythonList();
                foreach (var s in _数据数组)
                {
                    list.append(s);
                }
                return list;
            }
        }


        public string 按索引取值(int index)
        {
            if (_数据数组 == null || _数据数组.Length <= 0) return null;
            if (index < 0 || index >= _数据数组.Length) return null;

            return _数据数组[index];
        }

        public string 取字段值(string fieldName, bool ignoreCase = true)
        {
            if (string.IsNullOrEmpty(fieldName)) return null;
            if (_宿主数据表 == null) return null;

            var index = _宿主数据表.IndexOf(this);
            if (index < 0) return null;

            return _宿主数据表.取字段值(index, fieldName, ignoreCase);
        }

        /// <summary>
        /// 返回第一个符合条件的索引。
        /// </summary>
        /// <param name="val">要在行中查找的字符串值。</param>
        /// <returns>是否忽略大小写。</returns>
        public int 取值的索引(string val, bool ignoreCase = false)
        {
            if (_数据数组 == null || _数据数组.Length <= 0) return -1;

            for (int i = 0; i < _数据数组.Length; i++)
            {
                var txt = _数据数组[i];
                if (txt == null) txt = "";

                if (ignoreCase)
                {
                    if (val.ToLower() == txt.ToLower()) return i;
                }
                else
                {
                    if (val == txt) return i;
                }
            }

            return -1;
        }

        /// <summary>
        /// 返回所有符合条件的索引列表。
        /// </summary>
        /// <param name="val">要在行中查找的字符串值。</param>
        /// <param name="ignoreCase">是否忽略大小写。</param>
        /// <returns></returns>
        public List<int> 取值的索引集(string val, bool ignoreCase = false)
        {
            if (_数据数组 == null || _数据数组.Length <= 0) return null;

            var list = new List<int>();

            for (int i = 0; i < _数据数组.Length; i++)
            {
                var txt = _数据数组[i];
                if (txt == null) txt = "";

                if (ignoreCase)
                {
                    if (val.ToLower() == txt.ToLower()) list.Add(i);
                }
                else
                {
                    if (val == txt) list.Add(i);
                }
            }

            if (list.Count <= 0) return null;

            return list;
        }

        public string 取记录文本(bool ignoreBlankFields = false, IronPython.Runtime.PythonList names = null)
        {
            if (_数据数组 == null || _数据数组.Length <= 0)
                throw new Exception("此文本数据行的数据数组为空。");

            if (_宿主数据表 == null)
                throw new Exception("宿主数据表为空。");

            if (_宿主数据表.字段名行 == null || _宿主数据表.字段名行._数据数组 == null ||
                _宿主数据表.字段名行._数据数组.Length <= 0)
                throw new Exception("宿主数据表的字段名行为空或无成员。");

            if (_宿主数据表.字段名行._数据数组.Length != this._数据数组.Length)
                throw new Exception("宿主数据表字段名行的成员数与当前数据行的成员数不等。");

            string[][] array = new string[_数据数组.Length][];

            var maxWidth = 0;
            if (names != null && names.Count > 0)
            {
                for (int i = 0; i < _数据数组.Length; i++)
                {
                    array[i] = new string[2];
                    array[i][0] = _宿主数据表.字段名行.数据数组[i];
                    if (array[i][0] == null || string.IsNullOrWhiteSpace(array[i][0].Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim()))
                    {
                        array[i][0] = "[未知字段名]";
                    }

                    if (names.Contains(array[i][0]) == false) continue;

                    maxWidth = Math.Max(maxWidth, 纯文本处理器.取文本宽度(array[i][0]));
                    array[i][1] = _数据数组[i];
                }
            }
            else
            {
                for (int i = 0; i < _数据数组.Length; i++)
                {
                    array[i] = new string[2];
                    array[i][0] = _宿主数据表.字段名行.数据数组[i];
                    if (array[i][0] == null || string.IsNullOrWhiteSpace(array[i][0].Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim()))
                    {
                        array[i][0] = "[未知字段名]";
                    }
                    maxWidth = Math.Max(maxWidth, 纯文本处理器.取文本宽度(array[i][0]));
                    array[i][1] = _数据数组[i];
                }
            }

            var sb = new StringBuilder();
            sb.Append("[ 记录文本 >>>\r\n\r\n");

            int fieldsCount = 0;

            for (int i = 0; i < _数据数组.Length; i++)
            {
                string fieldName;
                if (array[i] == null || array[i].Length <= 0 || string.IsNullOrWhiteSpace(array[i][0]))
                {
                    fieldName = "[未知字段名]";
                }
                else
                {
                    fieldName = array[i][0].Trim();
                }

                if (string.IsNullOrWhiteSpace(fieldName))
                {
                    fieldName = "[未知字段名]";
                }
                else
                {
                    fieldName = fieldName.Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim();
                }

                string fieldValue;
                if (array[i] == null || array[i].Length <= 0 || string.IsNullOrWhiteSpace(array[i][1]))
                {
                    fieldValue = "";
                }
                else
                {
                    fieldValue = array[i][1].Trim();
                }

                if (string.IsNullOrWhiteSpace(fieldValue))
                {
                    fieldValue = "";
                }
                else
                {
                    fieldValue = fieldValue.Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim();
                }

                if (ignoreBlankFields && string.IsNullOrWhiteSpace(fieldValue)) continue;

                sb.Append("；" + new string(' ', maxWidth - 纯文本处理器.取文本宽度(fieldName)) + fieldName + "：" + fieldValue + "\r\n");
                fieldsCount++;
            }

            sb.Append("\r\n]\r\n");

            if (fieldsCount <= 0) return "[未能导出合适的记录内容。]";

            return sb.ToString();
        }

        public IronPython.Runtime.PythonList 取记录列表(bool ignoreBlankFields = false, IronPython.Runtime.PythonList names = null)
        {
            if (_数据数组 == null || _数据数组.Length <= 0)
                throw new Exception("此文本数据行的数据数组为空。");

            if (_宿主数据表 == null)
                throw new Exception("宿主数据表为空。");

            if (_宿主数据表.字段名行 == null || _宿主数据表.字段名行._数据数组 == null ||
                _宿主数据表.字段名行._数据数组.Length <= 0)
                throw new Exception("宿主数据表的字段名行为空或无成员。");

            if (_宿主数据表.字段名行._数据数组.Length != this._数据数组.Length)
                throw new Exception("宿主数据表字段名行的成员数与当前数据行的成员数不等。");

            string[][] array = new string[_数据数组.Length][];

            var maxWidth = 0;
            if (names != null && names.Count > 0)
            {
                for (int i = 0; i < _数据数组.Length; i++)
                {
                    array[i] = new string[2];
                    array[i][0] = _宿主数据表.字段名行.数据数组[i];
                    if (array[i][0] == null || string.IsNullOrWhiteSpace(array[i][0].Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim()))
                    {
                        array[i][0] = "[未知字段名]";
                    }

                    if (names.Contains(array[i][0]) == false) continue;

                    maxWidth = Math.Max(maxWidth, 纯文本处理器.取文本宽度(array[i][0]));
                    array[i][1] = _数据数组[i];
                }
            }
            else
            {
                for (int i = 0; i < _数据数组.Length; i++)
                {
                    array[i] = new string[2];
                    array[i][0] = _宿主数据表.字段名行.数据数组[i];
                    if (array[i][0] == null || string.IsNullOrWhiteSpace(array[i][0].Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim()))
                    {
                        array[i][0] = "[未知字段名]";
                    }
                    maxWidth = Math.Max(maxWidth, 纯文本处理器.取文本宽度(array[i][0]));
                    array[i][1] = _数据数组[i];
                }
            }

            IronPython.Runtime.PythonList plist = new IronPython.Runtime.PythonList();
            int fieldsCount = 0;

            for (int i = 0; i < _数据数组.Length; i++)
            {
                string fieldName;
                if (array[i] == null || array[i].Length <= 0 || string.IsNullOrWhiteSpace(array[i][0]))
                {
                    fieldName = "[未知字段名]";
                }
                else
                {
                    fieldName = array[i][0].Trim();
                }

                if (string.IsNullOrWhiteSpace(fieldName))
                {
                    fieldName = "[未知字段名]";
                }
                else
                {
                    fieldName = fieldName.Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim();
                }

                string fieldValue;
                if (array[i] == null || array[i].Length <= 0 || string.IsNullOrWhiteSpace(array[i][1]))
                {
                    fieldValue = "";
                }
                else
                {
                    fieldValue = array[i][1].Trim();
                }

                if (string.IsNullOrWhiteSpace(fieldValue))
                {
                    fieldValue = "";
                }
                else
                {
                    fieldValue = fieldValue.Replace("\r\n", "").Replace("\n", "").Replace("\r", "").Trim();
                }

                if (ignoreBlankFields && string.IsNullOrWhiteSpace(fieldValue)) continue;

                var subplist = new IronPython.Runtime.PythonList();
                subplist.Add(fieldName);
                subplist.Add(fieldValue);
                plist.Add(subplist);
                fieldsCount++;
            }

            if (fieldsCount <= 0) return null;

            return plist;
        }

        /// <summary>
        /// 此方法用以判断当前指定文本是否出现在当前文本数据行的指定的那几个字段中。
        /// 注意：1. 此方法总是忽略大小写，但不会忽略全角、半角的区别。
        ///       2. 此方法依赖宿主文本数据表（也就是当前文本数据行必须在某个文本数据表中才能使用此方法）。
        /// </summary>
        /// <param name="val">要查询的文本值。如传入的是 null，会视为空字符串。</param>
        /// <param name="fields">需要比对的字段名。注意：字段名不能为空字符串。</param>
        /// <returns>逻辑值。</returns>
        public bool 值在指定字段(string val, IronPython.Runtime.PythonList fields)
        {
            if (string.IsNullOrEmpty(val)) val = "";
            if (fields == null || fields.Count <= 0) return false;
            if (_宿主数据表 == null)
                throw new Exception("此文本数据行不在宿主文本数据表中，无法按字段名查询值是否在指定字段中。");

            var index = _宿主数据表.IndexOf(this);
            if (index < 0)
                throw new Exception("此文本数据行不在宿主文本数据表中，无法按字段名查询值是否在指定字段中。");

            foreach (var fieldName in fields)
            {
                var fieldNameTxt = fieldName.ToString();
                if (string.IsNullOrEmpty(fieldNameTxt)) continue;

                var fieldValue = _宿主数据表.取字段值(index, fieldNameTxt, true);
                if (fieldValue.ToLower() == val.ToLower()) return true;
            }
            return false;
        }

        /// <summary>
        /// 此方法用以判断当前指定文本是否出现在当前文本数据行指定字段以外的其它字段中。
        /// 注意：1. 此方法总是忽略大小写，但不会忽略全角、半角的区别。
        ///       2. 此方法依赖宿主文本数据表（也就是当前文本数据行必须在某个文本数据表中才能使用此方法）。
        /// </summary>
        /// <param name="val">要查询的文本值。如传入的是 null，会视为空字符串。</param>
        /// <param name="fields">需要排除的字段名。</param>
        /// <returns>逻辑值。</returns>
        public bool 值在其它字段(string val, IronPython.Runtime.PythonList fields)
        {
            if (string.IsNullOrEmpty(val)) val = "";
            if (fields == null || fields.Count <= 0) return false;
            if (_宿主数据表 == null)
                throw new Exception("此文本数据行不在宿主文本数据表中，无法按字段名查询值是否在指定字段中。");

            var index = _宿主数据表.IndexOf(this);
            if (index < 0)
                throw new Exception("此文本数据行不在宿主文本数据表中，无法按字段名查询值是否在指定字段中。");

            var exFieldNamesList = new List<string>();
            foreach (var field in fields)
            {
                var fieldTxt = field.ToString();
                if (string.IsNullOrEmpty(fieldTxt)) continue;

                exFieldNamesList.Add(fieldTxt);
            }
            if (exFieldNamesList.Count <= 0) return 值在记录(val);

            foreach (var fieldNameTxt in _宿主数据表.字段名行.数据数组)
            {
                if (string.IsNullOrEmpty(fieldNameTxt)) continue;
                if (ItemExist(exFieldNamesList, fieldNameTxt)) continue;   // 这些字段排除

                var fieldValue = _宿主数据表.取字段值(index, fieldNameTxt, true);
                if (fieldValue.ToLower() == val.ToLower()) return true;
            }
            return false;
        }

        private static bool ItemExist(List<string> list, string val, bool ignoreCase = true)
        {
            if (list == null || list.Count <= 0) return false;
            if (string.IsNullOrEmpty(val)) val = "";

            foreach (var li in list)
            {
                if (li.ToLower() == val.ToLower()) return true;
            }
            return false;
        }

        /// <summary>
        /// 此方法用以判断当前文本数据行中任一字段值是否与指定值相等。
        /// 注意：1. 此方法总是忽略大小写，但不会忽略全角、半角的区别。
        ///       2. 此方法不依赖宿主文本数据表（也就是此文本数据行不在任何文本数据表中也有效）。
        /// </summary>
        /// <param name="val">要查询的文本值。如传入的是 null，会视为空字符串。</param>
        /// <returns>逻辑值。</returns>
        public bool 值在记录(string val)
        {
            if (string.IsNullOrEmpty(val)) val = "";

            foreach (var fieldValue in _数据数组)
            {
                var fieldVal = string.IsNullOrEmpty(fieldValue) ? "" : fieldValue;

                if (val.ToLower() == fieldVal.ToLower()) return true;
            }
            return false;
        }
    }

    public enum 错误打印模式
    {
        错误直接显示 = DisplayCellErrorType.ErrorDisplayOnSheet,    // display
        错误显示为空白 = DisplayCellErrorType.ErrorAsBlank,  // <blank>
        错误显示为划线 = DisplayCellErrorType.ErrorAsDashes,  // --
        错误显示为NA = DisplayCellErrorType.ErrorAsNA,    // #N/A
    }

    public enum 打印顺序
    {
        先行后列,
        先列后行
    }

    /// <summary>
    /// 从二维数组生成一个纯文本的表。
    /// 默认情况下首行是字段名列表数组。
    /// </summary>
    public class 文本数据表 : List<文本数据行>
    {
        /// <summary>
        /// 因为只支持一种构造方法，所以可以保证列表中每个成员数组都是等长的。
        /// </summary>
        /// <param name="dataArray"></param>
        /// <param name="firstRowIsFieldNames"></param>
        public 文本数据表(string[][] dataArray, bool firstRowIsFieldNames = true)
        {
            if (dataArray == null || dataArray.Length <= 0) return;

            _首行是字段名列表 = firstRowIsFieldNames;

            if (_首行是字段名列表)
            {
                _字段名行 = new 文本数据行(dataArray[0]);

                for (int i = 1; i < dataArray.Length; i++)
                {
                    this.Add(new 文本数据行(dataArray[i]) { 宿主数据表 = this, });
                }
            }
            else
            {
                foreach (var arr in dataArray)
                {
                    this.Add(new 文本数据行(arr) { 宿主数据表 = this, });
                }
            }
        }

        public 文本数据表(string[][] dataArray, string[] fieldNames)
        {
            if (dataArray == null || dataArray.Length <= 0 ||
                fieldNames == null || fieldNames.Length <= 0) return;

            _字段名行 = new 文本数据行(fieldNames);

            for (int i = 0; i < dataArray.Length; i++)
            {
                this.Add(new 文本数据行(dataArray[i]) { 宿主数据表 = this, });
            }
        }

        public 文本数据表(IronPython.Runtime.PythonList dataList, bool firstRowIsFieldNames = true, bool splitWithChars = true, string splitterText = "|｜")
        {
            if (dataList == null || dataList.Count <= 0) return;

            char[] splitterChars;
            if (string.IsNullOrEmpty(splitterText))
            {
                splitterChars = new char[] { '|', '｜' };
            }
            else
            {
                splitterChars = splitterText.ToCharArray();
            }

            _首行是字段名列表 = firstRowIsFieldNames;

            if (_首行是字段名列表)
            {
                var rowFieldDataList = dataList[0] as IronPython.Runtime.PythonList;
                if (rowFieldDataList != null)
                {
                    _字段名行 = new 文本数据行(rowFieldDataList);
                }
                else
                {
                    var rowFieldDataTuple = dataList[0] as IronPython.Runtime.PythonTuple;
                    if (rowFieldDataTuple != null)
                    {
                        _字段名行 = new 文本数据行(rowFieldDataList);
                    }
                    else
                    {
                        string dataText = (dataList[0] == null) ? "" : dataList[0].ToString();

                        if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                        {
                            _字段名行 = new 文本数据行(dataList[0].ToString().Split(splitterChars));
                        }
                        else
                        {
                            _字段名行 = new 文本数据行(new string[] { dataList[0].ToString() });
                        }
                    }
                }

                for (int i = 1; i < dataList.Count; i++)
                {
                    var rowDataList = dataList[i] as IronPython.Runtime.PythonList;
                    if (rowDataList != null)
                    {
                        this.Add(new 文本数据行(rowDataList) { 宿主数据表 = this, });
                    }
                    else
                    {
                        var rowDataTuple = dataList[i] as IronPython.Runtime.PythonTuple;
                        if (rowDataTuple != null)
                        {
                            this.Add(new 文本数据行(rowDataTuple) { 宿主数据表 = this, });
                        }
                        else
                        {
                            string dataText = (dataList[i] == null) ? "" : dataList[0].ToString();

                            if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                            {
                                this.Add(new 文本数据行(dataList[i].ToString().Split(splitterChars)) { 宿主数据表 = this, });
                            }
                            else
                            {
                                this.Add(new 文本数据行(new string[] { dataList[i].ToString() }) { 宿主数据表 = this, });
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < dataList.Count; i++)
                {
                    var rowDataList = dataList[i] as IronPython.Runtime.PythonList;
                    if (rowDataList != null)
                    {
                        this.Add(new 文本数据行(rowDataList) { 宿主数据表 = this, });
                    }
                    else
                    {
                        var rowDataTuple = dataList[i] as IronPython.Runtime.PythonTuple;
                        if (rowDataTuple != null)
                        {
                            this.Add(new 文本数据行(rowDataTuple) { 宿主数据表 = this, });
                        }
                        else
                        {
                            string dataText = (dataList[i] == null) ? "" : dataList[0].ToString();

                            if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                            {
                                this.Add(new 文本数据行(dataList[i].ToString().Split(splitterChars)) { 宿主数据表 = this, });
                            }
                            else
                            {
                                this.Add(new 文本数据行(new string[] { dataList[i].ToString() }) { 宿主数据表 = this, });
                            }
                        }
                    }
                }
            }
        }

        public 文本数据表(IronPython.Runtime.PythonTuple dataTuple, bool firstRowIsFieldNames = true, bool splitWithChars = true, string splitterText = "|｜")
        {
            if (dataTuple == null || dataTuple.Count <= 0) return;

            char[] splitterChars;
            if (string.IsNullOrEmpty(splitterText))
            {
                splitterChars = new char[] { '|', '｜' };
            }
            else
            {
                splitterChars = splitterText.ToCharArray();
            }

            _首行是字段名列表 = firstRowIsFieldNames;

            if (_首行是字段名列表)
            {
                var rowFieldDataList = dataTuple[0] as IronPython.Runtime.PythonList;
                if (rowFieldDataList != null)
                {
                    _字段名行 = new 文本数据行(rowFieldDataList);
                }
                else
                {
                    var rowFieldDataTuple = dataTuple[0] as IronPython.Runtime.PythonTuple;
                    if (rowFieldDataTuple != null)
                    {
                        _字段名行 = new 文本数据行(rowFieldDataList);
                    }
                    else
                    {
                        string dataText = (dataTuple[0] == null) ? "" : dataTuple[0].ToString();

                        if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                        {
                            _字段名行 = new 文本数据行(dataTuple[0].ToString().Split(splitterChars));
                        }
                        else
                        {
                            _字段名行 = new 文本数据行(new string[] { dataTuple[0].ToString() });
                        }
                    }
                }


                for (int i = 1; i < dataTuple.Count; i++)
                {
                    var rowDataList = dataTuple[i] as IronPython.Runtime.PythonList;
                    if (rowDataList != null)
                    {
                        this.Add(new 文本数据行(rowDataList) { 宿主数据表 = this, });
                    }
                    else
                    {
                        var rowDataTuple = dataTuple[i] as IronPython.Runtime.PythonTuple;
                        if (rowDataTuple != null)
                        {
                            this.Add(new 文本数据行(rowDataTuple) { 宿主数据表 = this, });
                        }
                        else
                        {
                            string dataText = (dataTuple[i] == null) ? "" : dataTuple[0].ToString();

                            if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                            {
                                this.Add(new 文本数据行(dataTuple[i].ToString().Split(splitterChars)) { 宿主数据表 = this, });
                            }
                            else
                            {
                                this.Add(new 文本数据行(new string[] { dataTuple[i].ToString() }) { 宿主数据表 = this, });
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < dataTuple.Count; i++)
                {
                    var rowDataList = dataTuple[i] as IronPython.Runtime.PythonList;
                    if (rowDataList != null)
                    {
                        this.Add(new 文本数据行(rowDataList) { 宿主数据表 = this, });
                    }
                    else
                    {
                        var rowDataTuple = dataTuple[i] as IronPython.Runtime.PythonTuple;
                        if (rowDataTuple != null)
                        {
                            this.Add(new 文本数据行(rowDataTuple) { 宿主数据表 = this, });
                        }
                        else
                        {
                            string dataText = (dataTuple[i] == null) ? "" : dataTuple[0].ToString();

                            if (splitWithChars && string.IsNullOrEmpty(dataText) == false)
                            {
                                this.Add(new 文本数据行(dataTuple[i].ToString().Split(splitterChars)) { 宿主数据表 = this, });
                            }
                            else
                            {
                                this.Add(new 文本数据行(new string[] { dataTuple[i].ToString() }) { 宿主数据表 = this, });
                            }
                        }
                    }
                }
            }
        }

        public 文本数据表(IronPython.Runtime.PythonTuple fieldTuple, IronPython.Runtime.PythonTuple recordTuple)
        {
            if (fieldTuple == null || fieldTuple.Count <= 0) return;
            if (recordTuple == null || recordTuple.Count <= 0) return;

            _字段名行 = new 文本数据行(fieldTuple);

            for (int i = 0; i < recordTuple.Count; i++)
            {
                var subList = recordTuple[i] as PythonList;
                if (subList != null)
                {
                    this.Add(new 文本数据行(subList) { 宿主数据表 = this, });
                }
                else
                {
                    var subTuple = recordTuple[i] as PythonTuple;
                    this.Add(new 文本数据行(subTuple) { 宿主数据表 = this, });
                }
            }
        }

        public 文本数据表(IronPython.Runtime.PythonList fieldList, IronPython.Runtime.PythonList recordList)
        {
            if (fieldList == null || fieldList.Count <= 0) return;
            if (recordList == null || recordList.Count <= 0) return;

            _字段名行 = new 文本数据行(fieldList);

            for (int i = 0; i < recordList.Count; i++)
            {
                var subList = recordList[i] as PythonList;
                if (subList != null)
                {
                    this.Add(new 文本数据行(subList) { 宿主数据表 = this, });
                }
                else
                {
                    var subTuple = recordList[i] as PythonTuple;
                    this.Add(new 文本数据行(subTuple) { 宿主数据表 = this, });
                }
            }
        }

        public 文本数据表(IronPython.Runtime.PythonTuple fieldTuple, IronPython.Runtime.PythonList recordList)
        {
            if (fieldTuple == null || fieldTuple.Count <= 0) return;
            if (recordList == null || recordList.Count <= 0) return;

            _字段名行 = new 文本数据行(fieldTuple);

            for (int i = 0; i < recordList.Count; i++)
            {
                var subList = recordList[i] as PythonList;
                if (subList != null)
                {
                    this.Add(new 文本数据行(subList) { 宿主数据表 = this, });
                }
                else
                {
                    var subTuple = recordList[i] as PythonTuple;
                    this.Add(new 文本数据行(subTuple) { 宿主数据表 = this, });
                }
            }
        }

        public 文本数据表(IronPython.Runtime.PythonList fieldList, IronPython.Runtime.PythonTuple recordTuple)
        {
            if (fieldList == null || fieldList.Count <= 0) return;
            if (recordTuple == null || recordTuple.Count <= 0) return;

            _字段名行 = new 文本数据行(fieldList);

            for (int i = 0; i < recordTuple.Count; i++)
            {
                var subList = recordTuple[i] as PythonList;
                if (subList != null)
                {
                    this.Add(new 文本数据行(subList) { 宿主数据表 = this, });
                }
                else
                {
                    var subTuple = recordTuple[i] as PythonTuple;
                    this.Add(new 文本数据行(subTuple) { 宿主数据表 = this, });
                }
            }
        }

        private bool _首行是字段名列表 = true;

        public bool 首行是字段名列表 { get { return _首行是字段名列表; } }

        private 文本数据行 _字段名行 = null;

        public 文本数据行 字段名行 { get { return _字段名行; } }

        public int 宽度
        {
            get
            {
                if (this.Count <= 0) return 0;

                return this[0].数据数组.Length;
            }
        }

        public int 列数 => 宽度;

        public int 高度
        {
            get { return this.Count; }
        }

        public int 行数 => 高度;

        public 文本数据行 取数据行(int dataRowIndex)
        {
            if (dataRowIndex < 0 || dataRowIndex >= this.Count)
                throw new Exception($"此文本数据表中只有{this.Count}行数据，索引值从 0 算起，指定的参数值过大。");

            return this[dataRowIndex];
        }

        public string[] 取字段名数组()
        {
            return 字段名行.数据数组;
        }

        public PythonList 取字段名列表()
        {
            return 字段名行.数据列表;
        }

        public PythonTuple 取字段名元组()
        {
            return 字段名行.数据元组;
        }

        /// <summary>
        /// 返回指定行中第一个与字段名匹配的值。
        /// </summary>
        /// <param name="rowIndex">指定数据行索引，从0开始算。</param>
        /// <param name="fieldName">fieldName。</param>
        /// <param name="ignoreCase">是否忽略大小写。</param>
        /// <returns></returns>
        public string 按字段名取某行对应值(int rowIndex, string fieldName, bool ignoreCase = true)
        {
            if (_首行是字段名列表 == false) return null;

            if (this.Count <= 0) return null;

            if (_字段名行 == null || _字段名行.数据数组 == null || _字段名行.数据数组.Length <= 0) return null;

            var row = 取数据行(rowIndex);

            return row.按索引取值(_字段名行.取值的索引(fieldName, ignoreCase));
        }

        public string 取字段值(int rowIndex, string fieldName, bool ignoreCase = true)
        {
            return 按字段名取某行对应值(rowIndex, fieldName, ignoreCase);
        }

        public string 取字段值(string fieldName, int rowIndex, bool ignoreCase = true)
        {
            return 按字段名取某行对应值(rowIndex, fieldName, ignoreCase);
        }

        /// <summary>
        /// 假设有下表：
        /// 学号 | 学生姓名 | 语文 | 数学 | 英语
        ///   1  |   张三   |  24  |  87  |  92
        ///   2  |   李四   |  45  |  94  |  76
        ///   3  |   王五   |  78  |  55  |  39
        ///   4  |   赵六   |  94  |  79  |  58
        /// 此方法的功能类似于从成绩册中查询“姓名”为“张三”的学生的“语文”成绩。
        /// 注意：无论是行还是列，只要找到第一个就算！不会考虑后面的行、列是否还有符合条件的字段或值。
        /// </summary>
        /// <param name="baseFieldName">查询基准字段名。（例如：“姓名”）</param>
        /// <param name="baseFieldValue">查询基准字段值。（例如：“张三”）</param>
        /// <param name="destFieldName">查询目标字段名。（例如：“语文”）</param>
        /// <returns></returns>
        public string 查询数据(string baseFieldName, string baseFieldValue, string destFieldName, bool ignoreCase = true)
        {
            if (this.宽度 == 0 || this.高度 == 0 || this.首行是字段名列表 == false) return null;

            var fieldNamesArray = 取字段名数组();
            if (fieldNamesArray == null || fieldNamesArray.Length == 0) return null;

            if (baseFieldName == null) baseFieldName = "";
            if (baseFieldValue == null) baseFieldValue = "";
            if (destFieldName == null) destFieldName = "";

            baseFieldName = baseFieldName.Trim();
            baseFieldValue = baseFieldValue.Trim();
            destFieldName = destFieldName.Trim();

            if (ignoreCase)
            {
                baseFieldName = baseFieldName.ToLower();
                baseFieldValue = baseFieldValue.ToLower();
                destFieldName = destFieldName.ToLower();

                var baseFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].ToLower().Trim() == baseFieldName)
                    {
                        baseFieldColIndex = i;
                        break;
                    }
                }
                if (baseFieldColIndex < 0) return null;

                var destFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].ToLower().Trim() == destFieldName)
                    {
                        destFieldColIndex = i;
                        break;
                    }
                }
                if (destFieldColIndex < 0) return null;

                for (int i = 0; i < this.高度; i++)
                {
                    var dataRow = this[i];
                    if (dataRow.按索引取值(baseFieldColIndex).ToLower().Trim() == baseFieldValue)
                    {
                        return 取字段值(i, destFieldName, true);
                    }
                }
            }
            else
            {
                var baseFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].Trim() == baseFieldName)
                    {
                        baseFieldColIndex = i;
                        break;
                    }
                }
                if (baseFieldColIndex < 0) return null;

                var destFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].Trim() == destFieldName)
                    {
                        destFieldColIndex = i;
                        break;
                    }
                }
                if (destFieldColIndex < 0) return null;

                for (int i = 0; i < this.高度; i++)
                {
                    var dataRow = this[i];
                    if (dataRow.按索引取值(baseFieldColIndex).Trim() == baseFieldValue)
                    {
                        return 取字段值(i, destFieldName, false);
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 此方法按照特定字段名、字段值到当前工作表中查询所有符合此条件的记录行并返回一个列表。
        /// </summary>
        /// <param name="baseFieldName">要查询的字段名。</param>
        /// <param name="baseFieldValue">要查询的字段值。</param>
        /// <param name="ignoreCase">是否忽略大小写。</param>
        /// <returns>返回 IronPythonList 实例，其中每个成员都是 文本数据行 类的实例。</returns>
        public IronPython.Runtime.PythonList 查询记录(string baseFieldName, string baseFieldValue, string destFieldName, bool ignoreCase)
        {
            if (this.宽度 == 0 || this.高度 == 0 || this.首行是字段名列表 == false) return null;

            var fieldNamesArray = 取字段名数组();
            if (fieldNamesArray == null || fieldNamesArray.Length == 0) return null;

            if (baseFieldName == null) baseFieldName = "";
            if (baseFieldValue == null) baseFieldValue = "";
            if (destFieldName == null) destFieldName = "";

            baseFieldName = baseFieldName.Trim();
            baseFieldValue = baseFieldValue.Trim();
            destFieldName = destFieldName.Trim();

            var list = new IronPython.Runtime.PythonList();

            if (ignoreCase)
            {
                baseFieldName = baseFieldName.ToLower();
                baseFieldValue = baseFieldValue.ToLower();
                destFieldName = destFieldName.ToLower();

                var baseFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].ToLower().Trim() == baseFieldName)
                    {
                        baseFieldColIndex = i;
                        break;
                    }
                }
                if (baseFieldColIndex < 0) return null;

                var destFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].ToLower().Trim() == destFieldName)
                    {
                        destFieldColIndex = i;
                        break;
                    }
                }
                if (destFieldColIndex < 0) return null;

                for (int i = 0; i < this.高度; i++)
                {
                    var dataRow = this[i];
                    if (dataRow.按索引取值(baseFieldColIndex).ToLower().Trim() == baseFieldValue)
                    {
                        list.Add(dataRow);
                    }
                }
            }
            else
            {
                var baseFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].Trim() == baseFieldName)
                    {
                        baseFieldColIndex = i;
                        break;
                    }
                }
                if (baseFieldColIndex < 0) return null;

                var destFieldColIndex = -1;
                for (int i = 0; i < fieldNamesArray.Length; i++)
                {
                    if (fieldNamesArray[i].Trim() == destFieldName)
                    {
                        destFieldColIndex = i;
                        break;
                    }
                }
                if (destFieldColIndex < 0) return null;

                for (int i = 0; i < this.高度; i++)
                {
                    var dataRow = this[i];
                    if (dataRow.按索引取值(baseFieldColIndex).Trim() == baseFieldValue)
                    {
                        list.Add(dataRow);
                    }
                }
            }

            return list;
        }

        public string[] 按字段名取某行对应值数组(int rowIndex, string fieldName, bool ignoreCase = true)
        {
            if (_首行是字段名列表 == false) return null;

            if (this.Count <= 0) return null;

            if (_字段名行 == null || _字段名行.数据数组 == null || _字段名行.数据数组.Length <= 0) return null;

            var row = 取数据行(rowIndex);

            var iList = _字段名行.取值的索引集(fieldName, ignoreCase);

            if (iList == null || iList.Count <= 0) return null;

            var resultArray = new string[iList.Count];
            for (int j = 0; j < iList.Count; j++)
            {
                resultArray[j] = row.按索引取值(iList[j]);
            }
            return resultArray;
        }

        public string 按索引取某行对应值(int rowIndex, int colIndex)
        {
            if (this.Count <= 0) return null;

            var row = 取数据行(rowIndex);
            if (row == null) return null;

            return row.按索引取值(colIndex);
        }

        public string[] 按索引集取某行对应值数组(int rowIndex, int[] iList)
        {
            if (iList == null || iList.Length <= 0) return null;

            var row = 取数据行(rowIndex);

            if (row == null || row.数据数组.Length <= 0) return null;

            var list = new List<string>();
            for (int i = 0; i < iList.Length; i++)
            {
                var index = iList[i];
                if (index < 0 || index >= row.数据数组.Length) continue;

                list.Add(row.按索引取值(index));
            }

            if (list.Count <= 0) return null;

            return list.ToArray<string>();
        }

        /// <summary>
        /// 此方法功能类似于邮件合并，用于将当前数据集中的记录（的部分字段）逐次按照指定位置填充到一张新表中的特定区域。
        /// 填充时：
        /// 1. 先将模板中的内容复制到新表指定区域（这个区域的大小是由模板区域决定的）；
        /// 2. 将记录中的字段再填充到这个区域中的指定位置。
        /// </summary>
        /// <param name="tempSheet">模板所在的工作表。</param>
        /// <param name="tempRange">CellRangeAddress。</param>
        /// <param name="destSheet">要导出的新表。注意不能为空，也不能重复</param>
        /// <param name="locations">要填充的单元格的位置信息列表。这里的位置是相对于模板区域左上角的相对位置，以模板左上角那一格为（0,0）。</param>
        /// <param name="addPageBreaker">是否在每条记录导出时在导出区域左上角添加分页符。</param>
        /// <param name="cols">导出区域横向栏数。默认为 1。</param>
        /// <param name="splitterRowCount">导出区域之间用于分隔的空白行数，默认为 1（最小也是 1）。</param>
        /// <returns>如果填充失败，返回 false，否则返回 true。</returns>
        public bool 按模板区域填充到新表(工作表 tempSheet, CellRangeAddress tempRange, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            if (tempSheet == null)
            {
                LMessageBox.ShowWarning("模板表不能为 null。");
                return false;
            }

            if (destSheet == null)
            {
                LMessageBox.ShowWarning("目标表不能为 null。");
                return false;
            }

            // 照搬页面设置。
            destSheet.工作表体.SetMargin(MarginType.LeftMargin, tempSheet.工作表体.GetMargin(MarginType.LeftMargin));
            destSheet.工作表体.SetMargin(MarginType.TopMargin, tempSheet.工作表体.GetMargin(MarginType.TopMargin));
            destSheet.工作表体.SetMargin(MarginType.RightMargin, tempSheet.工作表体.GetMargin(MarginType.RightMargin));
            destSheet.工作表体.SetMargin(MarginType.BottomMargin, tempSheet.工作表体.GetMargin(MarginType.BottomMargin));
            destSheet.工作表体.PrintSetup.HeaderMargin = tempSheet.工作表体.PrintSetup.HeaderMargin;
            destSheet.工作表体.PrintSetup.FooterMargin = tempSheet.工作表体.PrintSetup.FooterMargin;
            destSheet.工作表体.PrintSetup.PaperSize = tempSheet.工作表体.PrintSetup.PaperSize;

            if (locations == null || locations.Count <= 0)
            {
                LMessageBox.ShowWarning("未指定填充位置列表，或填充位置列表中没有位置信息。");
                return false;
            }

            //try
            //{

            var tempRangeColumnsCount = tempRange.LastColumn - tempRange.FirstColumn + 1;
            var tempRangeRowsCount = tempRange.LastRow - tempRange.FirstRow + 1;

            if (tempRangeColumnsCount > 50 || tempRangeRowsCount > 50)
            {
                if (this.行数 > 100 || this.列数 > 10)
                {
                    var answer = LMessageBox.ShowQuestion("选择的模板区域行数或列数超过 50，且用于填充的记录行数或列数超过了 100。\r\n" +
                        "　　因为要保留单元格样式，这样大的模板和填充记录会相当耗时，甚至导致程序长时间失去响应！\r\n" +
                        "　　建议将这些记录分批生成多个文本数据表，并分别填充到对应的新工作表中。\r\n\r\n" +
                        "　　如果继续操作，可能需要等待很长时间。\r\n\r\n您真的要继续执行此操作吗？");
                    if (answer != MessageBoxResult.Yes) return false;
                }
            }

            for (int i = 0; i < this.行数; i++)
            {
                // 根据栏数（cols）和记录索引，决定 复制模板区域的基准位置
                // 这是为了打印方便。
                // 例如：要在一张纸上打印一些小标签，并且需要在标签中填写一些文字。这张纸可以在宽度可以容纳多个标签。

                var modValue = i % cols;
                var divValue = (int)i / cols;
                locations.基准列号 = (tempRangeColumnsCount + 1) * modValue;
                locations.基准行号 = (tempRangeRowsCount + Math.Max(1, splitterRowCount)) * divValue;

                tempSheet.复制区域到其它表(tempRange.FirstRow, tempRange.LastRow, tempRange.FirstColumn,
                    tempRange.LastColumn, destSheet, locations.基准行号 - tempRange.FirstRow, locations.基准列号 - tempRange.FirstColumn);

                var record = this[i];
                foreach (var location in locations)
                {
                    var cell = destSheet.取单元格(locations.绝对行号(location), locations.绝对列号(location));

                    if (location.字段索引 < 0)
                    {
                        cell.置文本值("#VALUE!");
                        var newStyle = cell.创建单元格样式();
                        newStyle.置单元格背景色(单元格色彩标号.黄色);
                        cell.置单元格样式(newStyle);
                        continue;
                    }

                    if (location.填充为二维码)
                    {
                        cell.置文本值(record.按索引取值(location.字段索引), true, location.二维码Url转码, location.二维码行数, location.二维码列数, 20);
                    }
                    else
                    {
                        if (location.是否分页符)
                        {
                            destSheet.插入分页符(cell.单元格体.RowIndex);
                        }
                        else
                        {
                            if (location.自动转换布尔值)
                            {
                                var fieldValue = record.按索引取值(location.字段索引);
                                if (string.IsNullOrEmpty(fieldValue) == false)
                                {
                                    if (string.IsNullOrEmpty(location.真值文本) == false && fieldValue.ToLower() == location.真值文本)
                                    {
                                        cell.置文本值(location.填充真值替换文本());
                                    }
                                    else if (string.IsNullOrEmpty(location.假值文本) == false && fieldValue.ToLower() == location.假值文本)
                                    {
                                        cell.置文本值(location.填充假替换值文本());
                                    }
                                    else
                                    {
                                        // 这些是内置的几乎种
                                        switch (fieldValue.ToLower())
                                        {
                                            case "真":
                                                {
                                                    cell.置文本值("■真　□假");
                                                    break;
                                                }
                                            case "是":
                                                {
                                                    cell.置文本值("■是　□否");
                                                    break;
                                                }
                                            case "true":
                                                {
                                                    cell.置文本值("■True　□False");
                                                    break;
                                                }
                                            case "假":
                                                {
                                                    cell.置文本值("□真　■假");
                                                    break;
                                                }
                                            case "否":
                                                {
                                                    cell.置文本值("□是　■否");
                                                    break;
                                                }
                                            case "false":
                                                {
                                                    cell.置文本值("□True　■False");
                                                    break;
                                                }
                                            case "男":
                                            case "男性":
                                                {
                                                    cell.置文本值("■男性　□女性");
                                                    break;
                                                }
                                            case "女":
                                            case "女性":
                                                {
                                                    cell.置文本值("□男性　■女性");
                                                    break;
                                                }
                                            default:
                                                {
                                                    cell.置文本值(fieldValue);
                                                    break;
                                                }
                                        }
                                    }
                                }
                                else
                                {
                                    cell.置文本值("");
                                }
                            }
                            else
                            {
                                cell.置文本值(record.按索引取值(location.字段索引));
                            }
                        }
                    }
                }

                if (i > 0 & i % cols == 0)
                {
                    destSheet.插入分页符(locations.基准行号 - 1);
                }
            }

            return true;
            //}
            //catch (Exception ex)
            //{
            //    LMessageBox.Show(ex.Message);
            //    return false;
            //}
        }

        /// <summary>
        /// 此方法功能类似于邮件合并，用于将当前数据集中的记录（的部分字段）逐次按照指定位置填充到一张新表中的特定区域。
        /// 填充时：
        /// 1. 先将模板中的内容复制到新表指定区域（这个区域的大小是由模板区域决定的）；
        /// 2. 将记录中的字段再填充到这个区域中的指定位置。
        /// </summary>
        /// <param name="tempSheet">模板所在的工作表。</param>
        /// <param name="tempRangeMark">模板区域（例如：B2:G4）</param>
        /// <param name="destSheet">要导出的新表。注意不能为空，也不能重复</param>
        /// <param name="locations">要填充的单元格的位置信息列表。这里的位置是相对于模板区域左上角的相对位置，以模板左上角那一格为（0,0）。</param>
        /// <param name="addPageBreaker">是否在每条记录导出时在导出区域左上角添加分页符。</param>
        /// <param name="cols">导出区域横向栏数。默认为 1。</param>
        /// <param name="splitterRowCount">导出区域之间用于分隔的空白行数，默认为 1（最小也是 1）。</param>
        /// <returns>如果填充失败，返回 false，否则返回 true。</returns>
        public bool 按模板区域填充到新表(工作表 tempSheet, string tempRangeMark, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            if (string.IsNullOrEmpty(tempRangeMark))
            {
                LMessageBox.ShowWarning("未指定模板区域。");
                return false;
            }

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
            tempRangeMark = tempRangeMark.Replace("：", ":");
            if (reg.Match(tempRangeMark).Success == false)
            {
                LMessageBox.Show("模板区域字符串标记不合法！");
                return false;
            }

            // 这是要复制到目标表中的模板区域块，有几条记录就复制几次。
            var tempRange = CellRangeAddress.ValueOf(tempRangeMark);
            return 按模板区域填充到新表(tempSheet, tempRange, destSheet, locations, addPageBreaker, cols, splitterRowCount);
        }


        /// <summary>
        /// 此方法功能类似于邮件合并，用于将当前数据集中的记录（的部分字段）逐次按照指定位置填充到一张新表中的特定区域。
        /// 填充时：
        /// 1. 先将模板中的内容复制到新表指定区域（这个区域的大小是由模板区域决定的）；
        /// 2. 将记录中的字段再填充到这个区域中的指定位置。
        /// </summary>
        /// <param name="tempSheet">模板所在的工作表。</param>
        /// <param name="region">模板区域。</param>
        /// <param name="destSheet">要导出的新表。注意不能为空，也不能重复</param>
        /// <param name="locations">要填充的单元格的位置信息列表。这里的位置是相对于模板区域左上角的相对位置，以模板左上角那一格为（0,0）。</param>
        /// <param name="addPageBreaker">是否在每条记录导出时在导出区域左上角添加分页符。</param>
        /// <param name="cols">导出区域横向栏数。默认为 1。</param>
        /// <param name="splitterRowCount">导出区域之间用于分隔的空白行数，默认为 1（最小也是 1）。</param>
        /// <returns>如果填充失败，返回 false，否则返回 true。</returns>
        public bool 按模板区域填充到新表(工作表 tempSheet, 区域 region, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            if (region == null)
            {
                LMessageBox.ShowWarning("未提供模板数据区域！");
                return false;
            }

            // 这是要复制到目标表中的模板区域块，有几条记录就复制几次。
            return 按模板区域填充到新表(tempSheet, region.区域体, destSheet, locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, 区域 region, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), region, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(工作表 tempSheet, string tempRangeMark, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(tempSheet, tempRangeMark, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(工作表 tempSheet, CellRangeAddress tempRange, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(tempSheet, tempRange, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(工作表 tempSheet, 区域 tempRange, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(tempSheet, tempRange, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, string tempRangeMark, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), tempRangeMark, destSheet, locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, string tempRangeMark, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), tempRangeMark, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, CellRangeAddress tempRangeMark, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), tempRangeMark, destSheet, locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, CellRangeAddress tempRangeMark, ISheet destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), tempRangeMark, new 工作表(destSheet), locations, addPageBreaker, cols, splitterRowCount);
        }

        public bool 按模板区域填充到新表(ISheet tempSheet, 区域 tempRange, 工作表 destSheet, 填充位置列表 locations, bool addPageBreaker = false, int cols = 1, int splitterRowCount = 1)
        {
            return 按模板区域填充到新表(new 工作表(tempSheet), tempRange, destSheet, locations, addPageBreaker, cols, splitterRowCount);
        }

        public 文字表 到二维文字表()
        {
            var sb = new StringBuilder();
            if (this.字段名行 != null && this.字段名行.数据数组 != null && this.字段名行.数据数组.Length > 0)
            {
                sb.Append("｜");
                foreach (var fieldName in this.字段名行.数据数组)
                {
                    sb.Append(fieldName);
                    sb.Append("｜");
                }
                sb.Append("\r\n|-|\r\n");    // 有字段名行的情况下，要手工添加列定义行来分隔字段名行与数据行集。
            }

            foreach (var row in this)
            {
                if (row.数据数组 != null && row.数据数组.Length > 0)
                {
                    sb.Append("｜");
                    foreach (var fieldValue in row.数据数组)
                    {
                        sb.Append(fieldValue);
                        sb.Append("｜");
                    }
                    sb.Append("\r\n");
                }
            }

            return new 文字表(sb.ToString());
        }
    }

    public class 填充位置
    {
        public 填充位置(int rowIndex, int colIndex, int fieldIndex,
                        bool convertBoolValue = false,
                        string trueText = "是",
                        string trueReplaceText = "■是　□否",
                        string falseText = "否",
                        string falseReplaceText = "□是　■否",
                        string trueTemplateText = "",
                        string falseTemplateText = "",
                        bool fillAsQrCode = false,
                        bool encodeUrl = true,
                        int rowsCount = 1,
                        int colsCount = 1,
                        bool isPageSplitter = false)
        {
            _相对行号 = rowIndex;
            _相对列号 = colIndex;
            _字段索引 = fieldIndex;
            _自动转换布尔值 = convertBoolValue;
            _真值文本 = trueText;
            _真值替换文本 = trueReplaceText;
            _假值文本 = falseText;
            _假值替换文本 = falseReplaceText;
            _真值模板文本 = trueTemplateText;
            _假值模板文本 = falseTemplateText;
            _填充为二维码 = fillAsQrCode;
            _二维码Url转码 = encodeUrl;
            _二维码行数 = rowsCount;
            _二维码列数 = colsCount;
            _是否分页符 = isPageSplitter;
        }

        public static 填充位置 创建填充位置(string tempLeftTopCellMark, string destCellMark, int fieldIndex,
                                            bool autoConvertBoolValue = false,
                                            string trueText = "是",
                                            string trueReplaceText = "■是　□否",
                                            string falseText = "否",
                                            string falseReplaceText = "□是　■否",
                                            string trueTemplateText = "",
                                            string falseTemplateText = "",
                                            bool fillAsQrCode = false,
                                            bool encodeUrl = true,
                                            int rowsCount = 1,
                                            int colsCount = 1,
                                            bool isPageSplitter = false)
        {
            if (string.IsNullOrWhiteSpace(tempLeftTopCellMark))
            {
                LMessageBox.ShowWarning("模板左上角位置不能为空！");
                return null;
            }

            if (string.IsNullOrWhiteSpace(destCellMark))
            {
                LMessageBox.ShowWarning("目标单元格位置不能为空！");
                return null;
            }

            tempLeftTopCellMark = tempLeftTopCellMark.Trim();
            destCellMark = destCellMark.Trim();

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+");
            if (reg.Match(tempLeftTopCellMark).Success == false)
            {
                LMessageBox.ShowWarning("模板左上角位置字符串非法！");
                return null;
            }

            if (reg.Match(destCellMark).Success == false)
            {
                LMessageBox.ShowWarning("目标单元格位置字符串非法！");
                return null;
            }

            var tempLeftTopRange = CellRangeAddress.ValueOf(tempLeftTopCellMark);
            var destRange = CellRangeAddress.ValueOf(destCellMark);

            var rowOffset = destRange.FirstRow - tempLeftTopRange.FirstRow;
            var colOffset = destRange.FirstColumn - tempLeftTopRange.FirstColumn;

            if (rowOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格行号不能小于模板区域左上角行号！");
                return null;
            }

            if (colOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格列号不能小于模板区域左上角列号！");
                return null;
            }

            return new 填充位置(rowOffset, colOffset, fieldIndex,
                autoConvertBoolValue, trueText, trueReplaceText,
                falseText, falseReplaceText,
                trueTemplateText, falseTemplateText, fillAsQrCode, encodeUrl, rowsCount, colsCount, isPageSplitter);
        }

        public static 填充位置 创建二维码填充位置(string tempLeftTopCellMark, string destCellMark, int fieldIndex, bool encodeUrl = true, int rowsCount = 1, int colsCount = 1)
        {
            if (string.IsNullOrWhiteSpace(tempLeftTopCellMark))
            {
                LMessageBox.ShowWarning("模板左上角位置不能为空！");
                return null;
            }

            if (string.IsNullOrWhiteSpace(destCellMark))
            {
                LMessageBox.ShowWarning("目标单元格位置不能为空！");
                return null;
            }

            tempLeftTopCellMark = tempLeftTopCellMark.Trim();
            destCellMark = destCellMark.Trim();

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+");
            if (reg.Match(tempLeftTopCellMark).Success == false)
            {
                LMessageBox.ShowWarning("模板左上角位置字符串非法！");
                return null;
            }

            if (reg.Match(destCellMark).Success == false)
            {
                LMessageBox.ShowWarning("目标单元格位置字符串非法！");
                return null;
            }

            var tempLeftTopRange = CellRangeAddress.ValueOf(tempLeftTopCellMark);
            var destRange = CellRangeAddress.ValueOf(destCellMark);

            var rowOffset = destRange.FirstRow - tempLeftTopRange.FirstRow;
            var colOffset = destRange.FirstColumn - tempLeftTopRange.FirstColumn;

            if (rowOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格行号不能小于模板区域左上角行号！");
                return null;
            }

            if (colOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格列号不能小于模板区域左上角列号！");
                return null;
            }

            return new 填充位置(rowOffset, colOffset, fieldIndex, false,
                "是", "■是　□否", "否", "□是　■否", "", "", true, encodeUrl, rowsCount, colsCount, false);
        }

        public static 填充位置 创建分页符填充位置(string tempLeftTopCellMark, string destCellMark)
        {
            if (string.IsNullOrWhiteSpace(tempLeftTopCellMark))
            {
                LMessageBox.ShowWarning("模板左上角位置不能为空！");
                return null;
            }

            if (string.IsNullOrWhiteSpace(destCellMark))
            {
                LMessageBox.ShowWarning("目标单元格位置不能为空！");
                return null;
            }

            tempLeftTopCellMark = tempLeftTopCellMark.Trim();
            destCellMark = destCellMark.Trim();

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+");
            if (reg.Match(tempLeftTopCellMark).Success == false)
            {
                LMessageBox.ShowWarning("模板左上角位置字符串非法！");
                return null;
            }

            if (reg.Match(destCellMark).Success == false)
            {
                LMessageBox.ShowWarning("目标单元格位置字符串非法！");
                return null;
            }

            var tempLeftTopRange = CellRangeAddress.ValueOf(tempLeftTopCellMark);
            var destRange = CellRangeAddress.ValueOf(destCellMark);

            var rowOffset = destRange.FirstRow - tempLeftTopRange.FirstRow;
            var colOffset = destRange.FirstColumn - tempLeftTopRange.FirstColumn;

            if (rowOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格行号不能小于模板区域左上角行号！");
                return null;
            }

            if (colOffset < 0)
            {
                LMessageBox.ShowWarning("目标单元格列号不能小于模板区域左上角列号！");
                return null;
            }

            return new 填充位置(rowOffset, colOffset, 0, false,
                "是", "■是　□否", "否", "□是　■否", "", "", false, true, 1, 1, true);
        }

        public static 填充位置 创建(string tempLeftTopCellMark, string destCellMark, int fieldIndex,
                                            bool autoConvertBoolValue = false,
                                            string trueText = "是",
                                            string trueReplaceText = "■是　□否",
                                            string falseText = "否",
                                            string falseReplaceText = "□是　■否",
                                            string trueTemplateText = "",
                                            string falseTemplateText = "",
                                            bool fillAsQrCode = false,
                                            bool encodeUrl = true,
                                            int rowsCount = 1,
                                            int colsCount = 1,
                                            bool isPageSplitter = false)
        {
            return 创建填充位置(tempLeftTopCellMark, destCellMark, fieldIndex,
                autoConvertBoolValue, trueText, trueReplaceText, falseText,
                falseReplaceText, trueTemplateText, falseTemplateText, fillAsQrCode, encodeUrl, rowsCount, colsCount, isPageSplitter);
        }

        private int _相对行号 = 0;

        public int 相对行号
        {
            get { return _相对行号; }
            set { _相对行号 = value; }
        }

        private int _相对列号 = 0;

        public int 相对列号
        {
            get { return _相对列号; }
            set { _相对列号 = value; }
        }

        private int _字段索引 = 0;

        public int 字段索引
        {
            get { return _字段索引; }
            set { _字段索引 = value; }
        }

        private bool _自动转换布尔值 = false;

        public bool 自动转换布尔值
        {
            get { return _自动转换布尔值; }
            set { _自动转换布尔值 = value; }
        }

        private string _真值文本;

        public string 真值文本
        {
            get { return _真值文本; }
            set { _真值文本 = value; }
        }

        private string _真值替换文本;

        public string 真值替换文本
        {
            get { return _真值替换文本; }
            set { _真值替换文本 = value; }
        }

        public string 填充真值替换文本()
        {
            if (string.IsNullOrWhiteSpace(_真值模板文本))
            {
                if (string.IsNullOrWhiteSpace(_真值替换文本) == false)
                {
                    return _真值替换文本;
                }
                else return _真值文本;
            }

            var pieces = Utils.Text.SplitToPiecesByRegex(@"\{.*?\}", _真值模板文本, true, true);
            var matchedPiecesCount = 0;

            var result = new StringBuilder();
            foreach (var piece in pieces)
            {
                if (piece.IsMartchText)
                {
                    if (string.IsNullOrWhiteSpace(_真值替换文本))
                    {
                        if (string.IsNullOrWhiteSpace(_真值文本))
                        {
                            result.Append("True");
                        }
                        else
                        {
                            result.Append(_真值文本);
                        }
                    }
                    else
                    {
                        result.Append(_真值替换文本);
                    }
                    matchedPiecesCount++;
                }
                else
                {
                    result.Append(piece.SourceText);
                }
            }
            return result.ToString();
        }

        private string _假值文本;

        public string 假值文本
        {
            get { return _假值文本; }
            set { _假值文本 = value; }
        }

        private string _假值替换文本;

        public string 假值替换文本
        {
            get { return _假值替换文本; }
            set { _假值替换文本 = value; }
        }

        public string 填充假替换值文本()
        {
            if (string.IsNullOrWhiteSpace(_假值模板文本))
            {
                if (string.IsNullOrWhiteSpace(_假值替换文本) == false)
                {
                    return _假值替换文本;
                }
                else return _假值文本;
            }

            var pieces = Utils.Text.SplitToPiecesByRegex(@"\{.*?\}", _假值模板文本, true, true);
            var matchedPiecesCount = 0;

            var result = new StringBuilder();
            foreach (var piece in pieces)
            {
                if (piece.IsMartchText)
                {
                    if (string.IsNullOrWhiteSpace(_假值替换文本))
                    {
                        if (string.IsNullOrWhiteSpace(_假值文本))
                        {
                            result.Append("True");
                        }
                        else
                        {
                            result.Append(_假值文本);
                        }
                    }
                    else
                    {
                        result.Append(_假值替换文本);
                    }
                    matchedPiecesCount++;
                }
                else
                {
                    result.Append(piece.SourceText);
                }
            }
            return result.ToString();
        }

        private string _真值模板文本;

        public string 真值模板文本
        {
            get { return _真值模板文本; }
            set { _真值模板文本 = value; }
        }

        private string _假值模板文本;

        public string 假值模板文本
        {
            get { return _假值模板文本; }
            set { _假值模板文本 = value; }
        }

        private bool _填充为二维码 = false;

        public bool 填充为二维码 { get { return _填充为二维码; } }

        private bool _二维码Url转码 = true;

        public bool 二维码Url转码 { get { return _二维码Url转码; } }

        private int _二维码行数 = 1;

        public int 二维码行数 { get { return _二维码行数; } }

        private int _二维码列数 = 1;

        public int 二维码列数 { get { return _二维码列数; } }

        private bool _是否分页符 = false;

        public bool 是否分页符 { get { return _是否分页符; } }
    }

    public class 填充位置列表 : List<填充位置>
    {
        private int _基准行号 = 0;

        public int 基准行号
        {
            get { return _基准行号; }
            set { _基准行号 = value; }
        }

        private int _基准列号 = 0;

        public int 基准列号
        {
            get { return _基准列号; }
            set { _基准列号 = value; }
        }

        public 填充位置列表 添加填充位置(填充位置 location)
        {
            this.Add(location);
            return this;
        }

        public 填充位置列表 添加填充位置(int rowIndex, int colIndex, int fieldIndex)
        {
            this.Add(new 填充位置(rowIndex, colIndex, fieldIndex));
            return this;
        }

        public int 绝对行号(填充位置 location)
        {
            return location.相对行号 + _基准行号;
        }

        public int 绝对列号(填充位置 location)
        {
            return location.相对列号 + _基准列号;
        }
    }

    public class 行
    {
        internal 行(IRow row, 工作表 sheet)
        {
            _行体 = row;
            _工作表 = sheet;
        }

        private IRow _行体;

        public IRow 行体
        {
            get { return _行体; }
        }

        /// <summary>
        /// 单位是 缇（1/20 point，或 1/1440 英寸，或 1/567 厘米）
        /// </summary>
        /// <param name="twips"></param>
        public 行 置行高(short twips)
        {
            _行体.Height = twips;
            return this;
        }

        /// <summary>
        /// 单位是 缇（1/20 point，或 1/1440 英寸，或 1/567 厘米）
        /// </summary>
        /// <returns></returns>
        public short 取行高()
        {
            return this._行体.Height;
        }
        /// <summary>
        /// 1 缇为 1/567 厘米。
        /// </summary>
        /// <param name="cm"></param>
        public 行 置厘米行高(double cm)
        {
            _行体.Height = (short)(cm * 567);
            return this;
        }

        /// <summary>
        /// 此方法假定当前工作表数据区域第一行为字段名行，并匹配第一个找到的字段名。
        /// </summary>
        /// <param name="字段名"></param>
        /// <returns></returns>
        public string 取字段值(string 字段名, bool ignoreCase = true)
        {
            if (_工作表 == null) return null;
            if (string.IsNullOrWhiteSpace(字段名)) return null;

            var dataRng = _工作表.数据区域;
            if (this._行体.RowNum <= dataRng.区域体.FirstRow || this._行体.RowNum > dataRng.区域体.LastRow) return null;
            // 如果此行就是标题行，也返回 null。

            var fieldRow = _工作表.取行(dataRng.区域体.FirstRow);

            var fieldCell = fieldRow.查找单元格(字段名, ignoreCase);
            if (fieldCell == null) return null;

            var fieldIndex = fieldCell.单元格列号;

            var dataCell = this.取单元格(fieldIndex);
            if (dataCell == null) return null;

            return dataCell.单元格体.StringCellValue;
        }

        public PythonList 取字段名列表()
        {
            if (this._工作表 == null)
                throw new Exception("此行不在任何宿主工作表中。");

            return this._工作表.取字段名列表();
        }

        public PythonList 筛选同名字段值(string fieldName, bool ignoreCase = true)
        {
            if (string.IsNullOrEmpty(fieldName)) return null;   // 字段值可以为空或Null，但字段名不能为空字符串
            if (this._工作表 == null) return null;

            var dataRng = this._工作表.数据区域;
            if (dataRng == null) return null;

            var fieldsRow = this._工作表.取行(dataRng.区域体.FirstRow);
            if (fieldsRow == null) return null;

            var list = new PythonList();
            for (int i = dataRng.区域体.FirstColumn; i <= dataRng.区域体.LastColumn; i++)
            {
                var fieldCell = fieldsRow.取单元格(i);
                if (fieldCell == null || string.IsNullOrEmpty(fieldCell.文本值)) continue;

                if (ignoreCase)
                {
                    if (fieldCell.文本值.ToLower() == fieldName.ToLower())  // 字段名不能为空或null
                    {
                        list.Add(this.取单元格(i).文本值);   // 字段值可以为 空字符串或 null
                    }
                }
                else
                {
                    if (fieldCell.文本值 == fieldName)    // 字段名不能为空或null
                    {
                        list.Add(this.取单元格(i).文本值);
                    }
                }
            }
            return list;
        }

        public PythonList 筛选字段值(string[] fields, bool ignoreCase = true)
        {
            if (fields == null || fields.Length <= 0) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(取字段值(field, ignoreCase));
            }
            return list;
        }

        public PythonList 筛选字段值(PythonTuple fields, bool ignoreCase = true)
        {
            if (fields == null || fields.Count <= 0) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(取字段值(field as string, ignoreCase));
            }
            return list;
        }

        public PythonList 筛选字段值(PythonList fields, bool ignoreCase = true)
        {
            if (fields == null || fields.Count <= 0) return null;

            var list = new PythonList();
            foreach (var field in fields)
            {
                list.Add(取字段值(field as string, ignoreCase));
            }
            return list;
        }

        public PythonList 取连续单元格文本列表(int colIndex, int cellCount)
        {
            if (colIndex < 0)
                throw new Exception("列索引不能小于 0。");

            if (cellCount < 1)
                throw new Exception("要获取值的单元格数目不能小于 1。");

            if (this._工作表 == null)
                throw new Exception("此行不在任意一个宿主工作表中。");

            var maxColIndex = this._工作表.最大列数 - 1;  // 列索引从 0 开始算

            if (colIndex > maxColIndex)
                throw new Exception($"起始列索引不能大于当前文档格式支持的最大列索引 {maxColIndex}。");

            var endIndex = colIndex + cellCount - 1;
            if (endIndex > maxColIndex)
                endIndex = maxColIndex;

            var list = new PythonList();
            for (int i = colIndex; i <= endIndex; i++)
            {
                var cell = this.取单元格(i);
                if (cell == null)
                {
                    list.Add(null);
                    continue;
                }

                var cellTxt = cell.文本值;
                if (cellTxt == null)
                {
                    list.Add(null);
                    continue;
                }

                list.Add(cellTxt);
            }

            return list;
        }

        public 行 向右填充字段(int colIndex, string[] values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Length <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var endIndex = colIndex + values.Length - 1;

            if (endIndex > maxColIndex)
                throw new Exception("粘贴列表过长，会导致右侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var index = values.Length - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index]);
                }
            }
            else
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i]);
                }
            }

            return this;
        }

        public 行 向右填充字段(int colIndex, PythonList values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Count <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var endIndex = colIndex + values.Count - 1;

            if (endIndex > maxColIndex)
                throw new Exception("粘贴列表过长，会导致右侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var index = values.Count - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index] as string);
                }
            }
            else
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i] as string);
                }
            }

            return this;
        }

        public 行 向右填充字段(int colIndex, PythonTuple values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Count <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var endIndex = colIndex + values.Count - 1;

            if (endIndex > maxColIndex)
                throw new Exception("粘贴列表过长，会导致右侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var index = values.Count - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index] as string);
                }
            }
            else
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i] as string);
                }
            }

            return this;
        }

        public 行 向左填充字段(int colIndex, string[] values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Length <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var startIndex = colIndex - values.Length + 1;

            if (startIndex < 0)
                throw new Exception("粘贴列表过长，会导致左侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var index = values.Length - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index]);
                }
            }
            else
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var cell = 取单元格(startIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i]);
                }
            }

            return this;
        }

        public 行 向左填充字段(int colIndex, PythonList values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Count <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var startIndex = colIndex - values.Count + 1;

            if (startIndex < 0)
                throw new Exception("粘贴列表过长，会导致左侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var index = values.Count - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index] as string);
                }
            }
            else
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var cell = 取单元格(startIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i] as string);
                }
            }
            return this;
        }

        public 行 向左填充字段(int colIndex, PythonTuple values, bool reverse = false)
        {
            if (colIndex < 0)
                throw new Exception("参数 colIndex 不能小于 0");

            if (this._工作表 == null)
                throw new Exception("此行没有宿主工作表。");

            if (values == null || values.Count <= 0)
                throw new Exception("未提供要填充的字值。");

            var maxColIndex = this._工作表.最大列数 - 1;

            if (colIndex > maxColIndex)
                throw new Exception($"参数 colIndex 不能大于当前文档支持的最大列索引 {maxColIndex}。");

            var startIndex = colIndex - values.Count + 1;

            if (startIndex < 0)
                throw new Exception("粘贴列表过长，会导致左侧越界。");

            if (reverse)
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var index = values.Count - 1 - i;
                    var cell = 取单元格(colIndex + i);
                    cell?.置文本值(values[index] == null ? "" : values[index] as string);
                }
            }
            else
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var cell = 取单元格(startIndex + i);
                    cell?.置文本值(values[i] == null ? "" : values[i] as string);
                }
            }

            return this;
        }

        /// <summary>
        /// 别名：取字段索引。
        /// 取当前行所在的数据区域第一行（视为字段名行）中匹配参数值的单元格在整个工作表中的实际列号。
        /// </summary>
        /// <param name="fieldName">要查找的字段名。</param>
        /// <returns>找不到返回 -1。</returns>
        private int 取字段列号(string fieldName, bool ignoreCase = true)
        {
            if (_工作表 == null) return -1;
            if (fieldName == null) fieldName = "";

            var dataRng = _工作表.数据区域;
            if (this._行体.RowNum < dataRng.区域体.FirstRow || this._行体.RowNum > dataRng.区域体.LastRow) return -1;

            var fieldRow = _工作表.取行(dataRng.区域体.FirstRow);

            var fieldCell = fieldRow.查找单元格(fieldName, ignoreCase);
            if (fieldCell == null) return -1;

            return fieldCell.单元格列号;
        }

        /// <summary>
        /// 别名：取字段列号。
        /// 取当前行所在的数据区域第一行（视为字段名行）中匹配参数值的单元格在整个工作表中的实际列号。
        /// </summary>
        /// <param name="fieldName">要匹配的字段名。</param>
        /// <returns>找不到返回 -1。</returns>
        private int 取字段索引(string fieldName, bool ignoreCase = true)
        {
            return 取字段列号(fieldName, ignoreCase);
        }



        /// <summary>
        /// 单位是厘米。（1厘米约为 567 缇）
        /// </summary>
        /// <returns></returns>
        public double 取厘米行高()
        {
            return _行体.Height / 567;
        }

        public 行 置毫米行高(double mm)
        {
            _行体.Height = (short)(mm * 56.7);
            return this;
        }

        public double 取毫米行高()
        {
            return _行体.Height / 56.7;
        }

        public 行 置点行高(float point)
        {
            _行体.HeightInPoints = point;
            return this;
        }

        public double 取点行高()
        {
            return _行体.HeightInPoints;
        }

        public 行 置磅行高(float point)
        {
            _行体.HeightInPoints = point;
            return this;
        }

        public double 取磅行高()
        {
            return _行体.HeightInPoints;
        }

        public 行 置缇行高(short twips)
        {
            _行体.Height = twips;
            return this;
        }

        public double 取缇行高()
        {
            return _行体.Height;
        }

        public int 取物理单元格数()
        {
            return _行体.PhysicalNumberOfCells;
        }

        public short 取首单元格列号()
        {
            return _行体.FirstCellNum;
        }

        public short 取尾单元格列号()
        {
            return _行体.LastCellNum;
        }

        public bool 是否设置了样式()
        {
            return _行体.IsFormatted;
        }

        public void 置行默认样式(单元格样式 style)
        {
            _行体.RowStyle = style.样式;
        }

        public 单元格样式 取行默认样式()
        {
            return new 单元格样式(_行体.RowStyle);
        }

        public 行 置行索引(int index)
        {
            _行体.RowNum = index;
            return this;
        }

        public int 取行索引()
        {
            return _行体.RowNum;
        }

        public bool 取是否折叠()
        {
            return _行体.Collapsed == true;
        }

        public bool 取是否隐藏()
        {
            return _行体.Hidden == true;
        }

        public int 取大纲级别()
        {
            return _行体.OutlineLevel;
        }

        public bool 取是否零高度()
        {
            return _行体.ZeroHeight;
        }

        public IronPython.Runtime.PythonList 取所有单元格()
        {
            if (this._行体.PhysicalNumberOfCells <= 0) return null;

            var list = new IronPython.Runtime.PythonList();
            foreach (var cell in _行体.Cells)
            {
                list.Add(new 单元格(cell, this.工作表, this));
            }
            return list;
        }

        public 单元格 创建单元格(int columnIndex)
        {
            if (columnIndex < 0) { columnIndex = 0; }

            if (_行体.Cells == null || _行体.Cells.Count - 1 < columnIndex - 1)
            {
                for (int i = _行体.Cells.Count; i <= columnIndex - 1; i++)
                {
                    _行体.CreateCell(i);
                }
            }

            return new 单元格(_行体.CreateCell(columnIndex), this.工作表, this);
        }

        public 单元格 取单元格(int columnIndex)
        {
            try
            {
                var cell = _行体.GetCell(columnIndex);
                if (cell == null)
                {
                    cell = 创建单元格(columnIndex).单元格体;
                }

                return new 单元格(cell, this.工作表, this);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 按当前行所在数据区域的第一行（视为字段名行）取指定名称的字段所在列号。然后按此列号取当前行中对应列的单元格。
        /// 注意：此行不能是数据区域第一行，也不能在数据区域之外。
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public 单元格 取字段单元格(string fieldName, bool ignoreCase)
        {
            var fieldColIndex = 取字段列号(fieldName, ignoreCase);
            if (fieldColIndex < 0) return null;

            return 取单元格(fieldColIndex);
        }

        /// <summary>
        /// 按当前行所在数据区域的第一行（视为字段名行）取指定名称的字段所在列号。然后按此列号取字段名行中对应列的单元格。
        /// 注意：数据区域第一行被视为字段名行。
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="ignoreCase"></param>
        /// <returns></returns>
        public 单元格 取字段名单元格(string fieldName, bool ignoreCase)
        {
            var fieldColIndex = 取字段列号(fieldName, ignoreCase);
            if (fieldColIndex < 0) return null;

            if (_工作表 == null) return null;

            var dataRange = _工作表.数据区域;
            if (dataRange.区域体.FirstRow < 0 || dataRange.区域体.FirstRow >= _工作表.最大行数) return null;

            var fieldNamesRow = _工作表.取行(dataRange.区域体.FirstRow);
            if (fieldNamesRow == null) return null;

            return fieldNamesRow.取单元格(fieldColIndex);
        }

        public int 查找单元格索引(string key, bool ignoreCase = true)
        {
            if (key == null) return -1;

            for (int i = 0; i < _行体.Cells.Count; i++)
            {
                var cell = _行体.Cells[i];
                if (ignoreCase)
                {
                    if (cell.StringCellValue.ToLower() == key.ToLower())
                    {
                        return i;
                    }
                }
                else
                {
                    if (cell.StringCellValue == key)
                    {
                        return i;
                    }
                }
            }

            return -1;
        }

        public 单元格 查找单元格(string key, bool ignoreCase = true)
        {
            if (key == null) return null;

            for (int i = 0; i < _行体.Cells.Count; i++)
            {
                var cell = _行体.Cells[i];
                if (ignoreCase)
                {
                    if (cell.StringCellValue.ToLower() == key.ToLower())
                    {
                        return new 单元格(cell, this.工作表, this);
                    }
                }
                else
                {
                    if (cell.StringCellValue == key)
                    {
                        return new 单元格(cell, this.工作表, this);
                    }
                }
            }

            return null;
        }

        public string[] 取值到字符串数组()
        {
            if (_行体.LastCellNum < 0) return null;

            string[] array = new string[_行体.LastCellNum - _行体.FirstCellNum];

            for (int i = _行体.FirstCellNum; i < _行体.LastCellNum; i++)
            {
                var cell = _行体.GetCell(i);
                if (cell == null)
                {
                    array[i] = "";
                }
                else
                {
                    switch (cell.CellType)
                    {
                        case CellType.Formula:
                            array[i] = cell.CellFormula.ToString(); break;
                        case CellType.Numeric:
                            array[i] = cell.NumericCellValue.ToString(); break;
                        case CellType.String:
                            array[i] = cell.StringCellValue; break;
                    }
                }
            }
            return array;
        }

        private 工作表 _工作表;

        public 工作表 工作表
        {
            get
            {
                if (_工作表 == null)
                {
                    return new 工作表(_行体.Sheet);
                }
                else
                {
                    return _工作表;
                }
            }
        }

        public 工作表 所属工作表
        {
            get => _工作表;
        }

        public 工作表 父工作表
        {
            get => _工作表;
        }
    }

    public class 单元格
    {
        internal 单元格(NPOI.SS.UserModel.ICell cell, 工作表 masterSheet, 行 masterRow)
        {
            _单元格体 = cell;
            _所属工作表 = masterSheet;
            _所属行 = masterRow;
        }

        private NPOI.SS.UserModel.ICell _单元格体;

        public NPOI.SS.UserModel.ICell 单元格体
        {
            get { return _单元格体; }
        }

        public int 单元格行号
        {
            get => this._单元格体.RowIndex;
        }

        private 工作表 _所属工作表;

        public 工作表 所属工作表
        {
            get => _所属工作表;
        }

        public 工作表 父工作表
        {
            get => _所属工作表;
        }

        private 行 _所属行;

        public 行 所属行
        {
            get => _所属行;
        }

        public 行 父行
        {
            get => _所属行;
        }

        public int 行索引 { get => this._单元格体.RowIndex; }

        public int 单元格列号
        {
            get => this._单元格体.ColumnIndex;
        }

        public int 列索引 { get => this._单元格体.ColumnIndex; }

        /// <summary>
        /// 将单元格的内容、样式复制到另一单元格中。
        /// 工作表类中会用到这个静态方法。
        /// </summary>
        /// <param name="srcCell">源单元格对象。</param>
        /// <param name="destCell">目标单元格对象。</param>
        internal static void CopyCell(NPOI.SS.UserModel.ICell srcCell, ICell destCell)
        {
            if (destCell != null && srcCell != null && destCell != srcCell)
            {
                //you can comment these out if you don't want to copy the style ...
                //destCell.CellComment = srcCell.CellComment;
                destCell.CellStyle = srcCell.CellStyle;
                //destCell.Hyperlink = srcCell.Hyperlink;

                switch (srcCell.CellType)
                {
                    case CellType.Formula:
                        destCell.CellFormula = srcCell.CellFormula; break;
                    case CellType.Numeric:
                        destCell.SetCellValue(srcCell.NumericCellValue); break;
                    case CellType.String:
                        destCell.SetCellValue(srcCell.StringCellValue); break;
                }
            }
        }

        public 单元格 复制到另一单元格(单元格 destCell)
        {
            CopyCell(this.单元格体, destCell.单元格体);
            return this;
        }

        public 单元格 复制到另一单元格(ICell destCell)
        {
            CopyCell(this.单元格体, destCell);
            return this;
        }

        public 单元格 置单元格类型(单元格类型 cellType)
        {
            // “文本单元格”“逻辑单元格”“空单元格”“错误单元格”“公式单元格”“数字单元格”“未知类型单元格”
            switch (cellType)
            {
                case NPOIHelp.单元格类型.文本单元格:
                    _单元格体.SetCellType(CellType.String);
                    break;
                case NPOIHelp.单元格类型.逻辑单元格:
                    _单元格体.SetCellType(CellType.Boolean);
                    break;
                case NPOIHelp.单元格类型.空单元格:
                    _单元格体.SetCellType(CellType.Blank);
                    break;
                case NPOIHelp.单元格类型.错误单元格:
                    _单元格体.SetCellType(CellType.Error);
                    break;
                case NPOIHelp.单元格类型.公式单元格:
                    _单元格体.SetCellType(CellType.Formula);
                    break;
                case NPOIHelp.单元格类型.数字单元格:
                    _单元格体.SetCellType(CellType.Numeric);
                    break;
                // case NPOIHelp.单元格类型.未知类型单元格:
                default:
                    _单元格体.SetCellType(CellType.Unknown);
                    break;
            }
            return this;
        }

        public 单元格 置单元格类型(string type)
        {
            // “文本单元格”“逻辑单元格”“空单元格”“错误单元格”“公式单元格”“数字单元格”“未知类型单元格”
            switch (type)
            {
                case "文本单元格":
                    _单元格体.SetCellType(CellType.String);
                    break;
                case "逻辑单元格":
                    _单元格体.SetCellType(CellType.Boolean);
                    break;
                case "空单元格":
                    _单元格体.SetCellType(CellType.Blank);
                    break;
                case "错误单元格":
                    _单元格体.SetCellType(CellType.Error);
                    break;
                case "公式单元格":
                    _单元格体.SetCellType(CellType.Formula);
                    break;
                case "数字单元格":
                    _单元格体.SetCellType(CellType.Numeric);
                    break;
                default:
                    _单元格体.SetCellType(CellType.Unknown);
                    break;
            }
            return this;
        }

        public 单元格 置单元格值(double newValue)
        {
            _单元格体.SetCellValue(newValue);
            return this;
        }

        public 单元格 置双精度值(double newValue)
        {
            _单元格体.SetCellValue(newValue);
            return this;
        }

        public 单元格 置布尔值(bool newValue)
        {
            _单元格体.SetCellValue(newValue);
            return this;
        }

        public 单元格 置日期时间值(int year, int month, int day, int hour, int minute, int second)
        {
            _单元格体.SetCellValue(new DateTime(year, month, day, hour, minute, second));
            return this;
        }

        public byte[] BitmapToByte(System.Drawing.Bitmap bitmap)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);  // 这里不能用 bmp，否则透明会丢失
            ms.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] bytes = new byte[ms.Length];
            ms.Read(bytes, 0, bytes.Length);
            ms.Dispose();
            return bytes;
        }

        public 单元格 置文本值(string newValue, bool toQrCode = false, bool encodeUrl = true,
            int rowsCount = 1, int colsCount = 1, float borderWidth = 20, string eccMark = "d")
        {
            if (toQrCode)
            {
                var eccEnum = ECCLevel.Default;

                switch (eccMark.ToLower().Trim())
                {
                    case "l":
                        {
                            eccEnum = ECCLevel.L; break;
                        }
                    case "m":
                        {
                            eccEnum = ECCLevel.M; break;
                        }
                    case "q":
                        {
                            eccEnum = ECCLevel.Q; break;
                        }
                    case "h":
                        {
                            eccEnum = ECCLevel.H; break;
                        }
                }

                var qrCodeIamge = QRBuilder.BuildQrCodeBitmap(newValue, eccEnum, null, 0, encodeUrl, true);
                var workbook = this.单元格体.Sheet.Workbook;
                var cell = this.单元格体;
                // qrCodeIamge.Save("d:\\aaa\\test_qr_image.png");
                if (borderWidth > 0)
                {
                    qrCodeIamge = qrCodeIamge.AddBorder(borderWidth);
                }
                var bytes = BitmapToByte(qrCodeIamge);

                if (IsMergeCell(this._单元格体.Sheet, this._单元格体.RowIndex, this._单元格体.ColumnIndex,
                    out int mrowsCount, out int mcolsCount) && mrowsCount >= 1 && mcolsCount >= 1)
                {
                    SetCellPhoto(workbook, cell, bytes, "png", mrowsCount, mcolsCount);
                }
                else
                {
                    SetCellPhoto(workbook, cell, bytes, "png", rowsCount, colsCount);
                }
            }
            else
            {
                _单元格体.SetCellValue(newValue);
            }
            return this;
        }

        public 单元格 置公式(string newValue)
        {
            _单元格体.SetCellFormula(newValue);  // 不需要 = 开头
            return this;
        }

        public string 单元格类型文本
        {
            get
            {
                switch (_单元格体.CellType)
                {
                    case CellType.String: return "文本单元格";
                    case CellType.Boolean: return "逻辑单元格";
                    case CellType.Blank: return "空单元格";
                    case CellType.Error: return "错误单元格";
                    case CellType.Formula: return "公式单元格";
                    case CellType.Numeric: return "数字单元格";
                    case CellType.Unknown: return "未知类型单元格";
                    default: return "未知类型单元格";
                }
            }
        }

        public string 单元格类型字符串
        {
            get => 单元格类型文本;
        }

        public 单元格类型 单元格类型
        {
            get
            {
                switch (_单元格体.CellType)
                {
                    case CellType.String: return 单元格类型.文本单元格;
                    case CellType.Boolean: return 单元格类型.逻辑单元格;
                    case CellType.Blank: return 单元格类型.空单元格;
                    case CellType.Error: return 单元格类型.错误单元格;
                    case CellType.Formula: return 单元格类型.公式单元格;
                    case CellType.Numeric: return 单元格类型.数字单元格;
                    default: return 单元格类型.未知类型单元格;
                }
            }
        }

        /// <summary>
        /// 默认取双精度值，等同于
        /// </summary>
        public double? 单元格值
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Numeric)
                {
                    throw new Exception($"“单元格值”（别名为“数字值”）这个属性用于获取数字值。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取数字值。");
                }

                return _单元格体.NumericCellValue;
            }
        }

        public bool? 逻辑值
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Boolean)
                {
                    throw new Exception($"“逻辑值”这个属性用于获取逻辑值。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取逻辑值。");
                }
                return _单元格体.BooleanCellValue;
            }
        }

        public DateTime? 日期时间值
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Numeric)
                {
                    throw new Exception($"“日期时间值”这个属性用于获取日期时间值。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取日期时间值。");
                }
                return _单元格体.DateCellValue.Value;
            }
        }

        public string 年月日文本
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Numeric)
                {
                    throw new Exception($"“年月日文本”这个属性用于获取日期时间值的“xxxx年xx月xx日”形式的字符串。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取日期时间值。");
                }
                var dt = _单元格体.DateCellValue;
                return $"{dt.Value.Year}年{dt.Value.Month}月{dt.Value.Day}日";
            }
        }

        public string 时分秒文本
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Numeric)
                {
                    throw new Exception($"“时分秒文本”这个属性用于获取日期时间值的“xx时xx分xx秒”形式的字符串。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取日期时间值。");
                }

                var dt = _单元格体.DateCellValue;
                return $"{dt.Value.Hour}时{dt.Value.Minute}分{dt.Value.Second}秒";
            }
        }

        public IronPython.Runtime.PythonTuple 时间信息元组
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Numeric)
                {
                    throw new Exception($"“时间信息元组”这个属性用于获取日期时间值（六个元素分别表示“年”“月”“日”“时”“分”“秒”）。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取日期时间值。");
                }

                var dt = _单元格体.DateCellValue;

                var tuple = new IronPython.Runtime.PythonTuple(
                    new int[]{
                    dt.Value.Year, dt.Value.Month, dt.Value.Day, dt.Value.Hour, dt.Value.Minute, dt.Value.Second });
                return tuple;
            }
        }

        public byte? 错误代码
        {
            get
            {
                if (_单元格体.CellType == CellType.Blank)
                {
                    return null;
                }

                if (_单元格体.CellType != CellType.Error)
                {
                    throw new Exception($"“错误代码”这个属性用于获取当前单元格中的错误代码。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能获取错误代码。");
                }
                return _单元格体.ErrorCellValue;
            }
        }

        public string 文本值
        {
            get
            {
                switch (_单元格体.CellType)
                {
                    case CellType.String: return _单元格体.StringCellValue;
                    case CellType.Boolean: return _单元格体.BooleanCellValue.ToString();
                    case CellType.Blank: return null;
                    case CellType.Error: return _单元格体.ErrorCellValue.ToString();
                    case CellType.Formula: return _单元格体.CellFormula;
                    case CellType.Numeric: return _单元格体.NumericCellValue.ToString();
                    // case CellType.Unknown: return "未知类型单元格";
                    default:
                        {
                            throw new Exception($"“文本值”这个属性用于获取当前单元格中的数据的文本形式。但（从0起算）{_单元格体.RowIndex}行{_单元格体.ColumnIndex}列处这个单元格类型是{this.单元格类型}，不能将获取单元格中的数据或转换成文本。");
                        }
                }
            }
        }

        public double? 数字值
        {
            get => this.单元格值;
        }

        public 单元格样式 取单元格样式()
        {
            if (_单元格体.CellStyle == null)
            {
                _单元格体.CellStyle = _单元格体?.Sheet?.Workbook?.CreateCellStyle();
            }
            return new 单元格样式(_单元格体.CellStyle);
        }

        public 单元格样式 创建单元格样式(单元格字体 cellFont = null)
        {
            var newStyle = new 单元格样式(this._单元格体.Sheet.Workbook.CreateCellStyle());
            if (cellFont != null)
            {
                newStyle.置单元格字体(cellFont);
            }
            return newStyle;
        }

        public 单元格字体 创建单元格字体()
        {
            return new 单元格字体(this._单元格体.Sheet.Workbook.CreateFont());
        }

        public 单元格 置单元格样式(单元格样式 newStyle)
        {
            _单元格体.CellStyle = newStyle.样式;
            return this;
        }

        public 单元格 置单元格数据格式(string partten)
        {
            var newFormat = _单元格体?.Sheet?.Workbook?.CreateDataFormat();
            if (newFormat == null) return this;

            _单元格体.CellStyle.DataFormat = newFormat.GetFormat(partten);
            return this;
        }

        public 单元格 置单元格数据格式(short formatIndex)
        {
            _单元格体.CellStyle.DataFormat = formatIndex;
            return this;
        }

        public bool 是否被合并
        {
            get => _单元格体.IsMergedCell;
        }

        void SetCellPhoto(IWorkbook workbook, NPOI.SS.UserModel.ICell cell, byte[] bytes, string extension, int rowsCount = 1, int colsCount = 1)
        {
            if (rowsCount < 1) rowsCount = 1;
            if (colsCount < 1) colsCount = 1;

            int pictureIdx;
            switch (extension.Trim(new char[] { ' ', '　', '\t', '.', ',' }).ToLower())
            {
                case "emf":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.EMF);
                        break;
                    }
                case "wmf":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.WMF);
                        break;
                    }
                case "pict":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.PICT);
                        break;
                    }
                case "jpg":
                case "jpeg":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.JPEG);
                        break;
                    }
                case "png":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.PNG);
                        break;
                    }
                case "dib":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.DIB);
                        break;
                    }
                case "gif":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.GIF);
                        break;
                    }
                case "tif":
                case "tiff":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.TIFF);
                        break;
                    }
                case "eps":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.EPS);
                        break;
                    }
                case "bmp":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.BMP);
                        break;
                    }
                case "wpg":
                    {
                        pictureIdx = workbook.AddPicture(bytes, NPOI.SS.UserModel.PictureType.WPG);
                        break;
                    }
                default:
                    {
                        throw new Exception("不能识别的图像格式。");
                    }
            }

            // 创建绘图对象
            var drawing = cell.Sheet.CreateDrawingPatriarch();

            XSSFClientAnchor anchor = new XSSFClientAnchor(
                1 * XSSFShape.EMU_PER_POINT, 1 * XSSFShape.EMU_PER_POINT, 1 * XSSFShape.EMU_PER_POINT, 1 * XSSFShape.EMU_PER_POINT,  // 横坐标 0-255，纵坐标 0-1023。这是反复测试的结果，不要乱改！！！
                cell.ColumnIndex,
                cell.RowIndex,
                cell.ColumnIndex + colsCount,
                cell.RowIndex + rowsCount);

            anchor.AnchorType = AnchorType.MoveAndResize;

            // 创建图片对象
            XSSFPicture pic = (XSSFPicture)drawing.CreatePicture(anchor, pictureIdx);

            // 设置图片的缩放大小，不能省略！
            pic.Resize(1, 1);  // 单元格尺寸较小时反复测试，用 1.03 较好贴合！！！
        }

        // 判断合并单元格重载
        // 调用时要在输出变量前加 out
        public bool IsMergeCell(ISheet sheet, int rowNum, int colNum, out int rowSpan, out int colSpan)
        {
            bool result = false;
            rowSpan = 0;
            colSpan = 0;
            if ((rowNum < 1) || (colNum < 1)) return result;
            int regionsCount = sheet.NumMergedRegions;
            rowSpan = 1;
            colSpan = 1;
            for (int i = 0; i < regionsCount; i++)
            {
                CellRangeAddress range = sheet.GetMergedRegion(i);
                sheet.IsMergedRegion(range);
                if (range.FirstRow == rowNum && range.FirstColumn == colNum)
                {
                    rowSpan = range.LastRow - range.FirstRow + 1;
                    colSpan = range.LastColumn - range.FirstColumn + 1;
                    break;
                }
            }
            try
            {
                var row = sheet.GetRow(rowNum); if (row != null)
                {
                    var cell = row.GetCell(colNum); if (cell != null)
                    {
                        result = cell.IsMergedCell;
                    }
                }
                else
                {
                    result = false;
                }
            }
            catch
            {
                result = false;
            }
            return result;
        }

        public 单元格 置单元格图像(string imgPath, int rowsCount = 1, int colsCount = 1)
        {
            var fi = new FileInfo(imgPath);
            var workbook = this.单元格体.Sheet.Workbook;
            var cell = this.单元格体;
            var bytes = File.ReadAllBytes(imgPath);
            if (IsMergeCell(this._单元格体.Sheet, this._单元格体.RowIndex, this._单元格体.ColumnIndex,
                out int mrowsCount, out int mcolsCount))
            {
                SetCellPhoto(workbook, cell, bytes, fi.Extension, mrowsCount, mcolsCount);
            }
            else
            {
                SetCellPhoto(workbook, cell, bytes, fi.Extension, rowsCount, colsCount);
            }

            return this;
        }

        /// <summary>
        /// 为保持向前兼容而保留。
        /// </summary>
        /// <param name="imgPath">图像文件路径。</param>
        /// <returns></returns>
        public 单元格 置单元格图像文件(string imgPath, int rowsCount = 1, int colsCount = 1)
        {
            return 置单元格图像(imgPath, rowsCount, colsCount);
        }

        public 单元格 置单元格图像(Bitmap bitmap, int rowsCount = 1, int colsCount = 1)
        {
            if (bitmap == null)
                throw new Exception("图像数据块不能为 None。");

            var workbook = this.单元格体.Sheet.Workbook;
            var cell = this.单元格体;
            var bytes = BitmapToByte(bitmap);
            if (IsMergeCell(this._单元格体.Sheet, this._单元格体.RowIndex, this._单元格体.ColumnIndex,
                out int mrowsCount, out int mcolsCount))
            {
                SetCellPhoto(workbook, cell, bytes, "bmp", mrowsCount, mcolsCount);
            }
            else
            {
                SetCellPhoto(workbook, cell, bytes, "bmp", rowsCount, colsCount);
            }

            return this;
        }
    }

    public class 单元格样式
    {
        internal 单元格样式(ICellStyle cellStyle, string styleName = "")
        {
            _样式 = cellStyle;
            if (string.IsNullOrWhiteSpace(styleName) == false)
            {
                _样式名 = styleName;
            }
        }

        private ICellStyle _样式;

        public ICellStyle 样式
        {
            get { return _样式; }
        }

        private string _样式名 = "未命名样式";

        public string 样式名 { get { return _样式名; } }

        public 单元格样式 置数据格式(string partten)
        {
            try
            {
                _样式.DataFormat = HSSFDataFormat.GetBuiltinFormat(partten);
                return this;
            }
            catch
            {
                _样式.DataFormat = 0;  // 0 是 “General”
                return this;
            }
        }

        public string 数据格式 { get { return _样式.GetDataFormatString(); } }

        public 单元格样式 置数据格式索引(int formatIndex)
        {
            _样式.DataFormat = (short)formatIndex;
            return this;
        }

        public bool 是否带引号前缀
        {
            get
            {
                return _样式.IsQuotePrefixed;
            }
            set
            {
                _样式.IsQuotePrefixed = value;
            }
        }

        public int 数据格式索引 { get { return _样式.DataFormat; } }

        public 单元格样式 置水平对齐(单元格水平对齐 align)
        {
            _样式.Alignment = (NPOI.SS.UserModel.HorizontalAlignment)(int)align;
            return this;
        }

        public 单元格水平对齐 水平对齐
        {
            get
            {
                switch (_样式.Alignment)
                {
                    case NPOI.SS.UserModel.HorizontalAlignment.General:
                        return 单元格水平对齐.水平通用;
                    case NPOI.SS.UserModel.HorizontalAlignment.Left:
                        return 单元格水平对齐.水平居左;
                    case NPOI.SS.UserModel.HorizontalAlignment.Center:
                        return 单元格水平对齐.水平居中;
                    case NPOI.SS.UserModel.HorizontalAlignment.Right:
                        return 单元格水平对齐.水平居右;
                    case NPOI.SS.UserModel.HorizontalAlignment.Justify:
                        return 单元格水平对齐.水平两端;
                    case NPOI.SS.UserModel.HorizontalAlignment.Fill:
                        return 单元格水平对齐.水平填充;
                    case NPOI.SS.UserModel.HorizontalAlignment.CenterSelection:
                        return 单元格水平对齐.水平跨列居中;
                    case NPOI.SS.UserModel.HorizontalAlignment.Distributed:
                        return 单元格水平对齐.水平分散;
                    default:
                        return 单元格水平对齐.水平通用;
                }
            }
        }

        public 单元格样式 置垂直对齐(单元格垂直对齐 align)
        {
            _样式.VerticalAlignment = (NPOI.SS.UserModel.VerticalAlignment)(int)align;
            return this;
        }

        public 单元格垂直对齐 垂直对齐
        {
            get
            {
                switch (_样式.VerticalAlignment)
                {
                    case NPOI.SS.UserModel.VerticalAlignment.None:
                        return 单元格垂直对齐.垂直无;
                    case NPOI.SS.UserModel.VerticalAlignment.Top:
                        return 单元格垂直对齐.垂直靠上;
                    case NPOI.SS.UserModel.VerticalAlignment.Center:
                        return 单元格垂直对齐.垂直居中;
                    case NPOI.SS.UserModel.VerticalAlignment.Bottom:
                        return 单元格垂直对齐.垂直靠下;
                    case NPOI.SS.UserModel.VerticalAlignment.Justify:
                        return 单元格垂直对齐.垂直两端;
                    case NPOI.SS.UserModel.VerticalAlignment.Distributed:
                        return 单元格垂直对齐.垂直分散;
                    default:
                        return 单元格垂直对齐.垂直居中;
                }
            }
        }

        public 单元格样式 置换行(bool newValue)
        {
            _样式.WrapText = newValue;
            return this;
        }

        public bool 换行 { get { return _样式.WrapText; } }

        public 单元格样式 置自动换行(bool newValue)
        {
            _样式.WrapText = newValue;
            return this;
        }

        public bool 自动换行 { get { return _样式.WrapText; } }

        public 单元格样式 置文本缩进(double newValue)
        {
            _样式.Indention = (short)newValue;
            return this;
        }

        public double 文本缩进 { get { return _样式.Indention; } }

        public 单元格样式 置文本旋转角度(double rotation)
        {
            if (rotation < -90) { rotation = -90; }

            if (rotation > 90) { rotation = 90; }

            _样式.Rotation = (short)rotation;
            return this;
        }

        public double 文本旋转角度 { get { return _样式.Rotation; } }

        public 单元格样式 置单元格左边框类型(单元格边框类型 newBorderStyle)
        {
            switch (newBorderStyle)
            {
                case 单元格边框类型.无边框:
                    _样式.BorderLeft = BorderStyle.None;
                    break;
                case 单元格边框类型.细边框:
                    _样式.BorderLeft = BorderStyle.Thin;
                    break;
                case 单元格边框类型.中号边框:
                    _样式.BorderLeft = BorderStyle.Medium;
                    break;
                case 单元格边框类型.划线边框:
                    _样式.BorderLeft = BorderStyle.Dashed;
                    break;
                case 单元格边框类型.点线边框:
                    _样式.BorderLeft = BorderStyle.Dotted;
                    break;
                case 单元格边框类型.厚边框:
                    _样式.BorderLeft = BorderStyle.Thick;
                    break;
                case 单元格边框类型.双线边框:
                    _样式.BorderLeft = BorderStyle.Double;
                    break;
                case 单元格边框类型.发宽边框:
                    _样式.BorderLeft = BorderStyle.Hair;
                    break;
                case 单元格边框类型.中号划线边框:
                    _样式.BorderLeft = BorderStyle.MediumDashed;
                    break;
                case 单元格边框类型.点划线边框:
                    _样式.BorderLeft = BorderStyle.DashDot;
                    break;
                case 单元格边框类型.中号点划线边框:
                    _样式.BorderLeft = BorderStyle.MediumDashDot;
                    break;
                case 单元格边框类型.点点划线边框:
                    _样式.BorderLeft = BorderStyle.DashDotDot;
                    break;
                case 单元格边框类型.中号点点划线边框:
                    _样式.BorderLeft = BorderStyle.MediumDashDotDot;
                    break;
                case 单元格边框类型.斜点划线边框:
                    _样式.BorderLeft = BorderStyle.SlantedDashDot;
                    break;
                default:
                    _样式.BorderLeft = BorderStyle.Thin;
                    break;
            }
            return this;
        }

        public 单元格边框类型 单元格左边框类型
        {
            get
            {
                switch (_样式.BorderLeft)
                {
                    case BorderStyle.None:
                        return 单元格边框类型.无边框;
                    case BorderStyle.Thin:
                        return 单元格边框类型.细边框;
                    case BorderStyle.Medium:
                        return 单元格边框类型.中号边框;
                    case BorderStyle.Dashed:
                        return 单元格边框类型.划线边框;
                    case BorderStyle.Dotted:
                        return 单元格边框类型.点线边框;
                    case BorderStyle.Thick:
                        return 单元格边框类型.厚边框;
                    case BorderStyle.Double:
                        return 单元格边框类型.双线边框;
                    case BorderStyle.Hair:
                        return 单元格边框类型.发宽边框;
                    case BorderStyle.MediumDashed:
                        return 单元格边框类型.中号划线边框;
                    case BorderStyle.DashDot:
                        return 单元格边框类型.点划线边框;
                    case BorderStyle.MediumDashDot:
                        return 单元格边框类型.中号点划线边框;
                    case BorderStyle.DashDotDot:
                        return 单元格边框类型.点点划线边框;
                    case BorderStyle.MediumDashDotDot:
                        return 单元格边框类型.中号点点划线边框;
                    case BorderStyle.SlantedDashDot:
                        return 单元格边框类型.斜点划线边框;
                    default:
                        return 单元格边框类型.无边框;
                }
            }
        }

        public 单元格样式 置单元格上边框类型(单元格边框类型 newBorderStyle)
        {
            switch (newBorderStyle)
            {
                case 单元格边框类型.无边框:
                    _样式.BorderTop = BorderStyle.None;
                    break;
                case 单元格边框类型.细边框:
                    _样式.BorderTop = BorderStyle.Thin;
                    break;
                case 单元格边框类型.中号边框:
                    _样式.BorderTop = BorderStyle.Medium;
                    break;
                case 单元格边框类型.划线边框:
                    _样式.BorderTop = BorderStyle.Dashed;
                    break;
                case 单元格边框类型.点线边框:
                    _样式.BorderTop = BorderStyle.Dotted;
                    break;
                case 单元格边框类型.厚边框:
                    _样式.BorderTop = BorderStyle.Thick;
                    break;
                case 单元格边框类型.双线边框:
                    _样式.BorderTop = BorderStyle.Double;
                    break;
                case 单元格边框类型.发宽边框:
                    _样式.BorderTop = BorderStyle.Hair;
                    break;
                case 单元格边框类型.中号划线边框:
                    _样式.BorderTop = BorderStyle.MediumDashed;
                    break;
                case 单元格边框类型.点划线边框:
                    _样式.BorderTop = BorderStyle.DashDot;
                    break;
                case 单元格边框类型.中号点划线边框:
                    _样式.BorderTop = BorderStyle.MediumDashDot;
                    break;
                case 单元格边框类型.点点划线边框:
                    _样式.BorderTop = BorderStyle.DashDotDot;
                    break;
                case 单元格边框类型.中号点点划线边框:
                    _样式.BorderTop = BorderStyle.MediumDashDotDot;
                    break;
                case 单元格边框类型.斜点划线边框:
                    _样式.BorderTop = BorderStyle.SlantedDashDot;
                    break;
                default:
                    _样式.BorderTop = BorderStyle.Thin;
                    break;
            }
            return this;
        }

        public 单元格边框类型 单元格上边框类型
        {
            get
            {
                switch (_样式.BorderTop)
                {
                    case BorderStyle.None:
                        return 单元格边框类型.无边框;
                    case BorderStyle.Thin:
                        return 单元格边框类型.细边框;
                    case BorderStyle.Medium:
                        return 单元格边框类型.中号边框;
                    case BorderStyle.Dashed:
                        return 单元格边框类型.划线边框;
                    case BorderStyle.Dotted:
                        return 单元格边框类型.点线边框;
                    case BorderStyle.Thick:
                        return 单元格边框类型.厚边框;
                    case BorderStyle.Double:
                        return 单元格边框类型.双线边框;
                    case BorderStyle.Hair:
                        return 单元格边框类型.发宽边框;
                    case BorderStyle.MediumDashed:
                        return 单元格边框类型.中号划线边框;
                    case BorderStyle.DashDot:
                        return 单元格边框类型.点划线边框;
                    case BorderStyle.MediumDashDot:
                        return 单元格边框类型.中号点划线边框;
                    case BorderStyle.DashDotDot:
                        return 单元格边框类型.点点划线边框;
                    case BorderStyle.MediumDashDotDot:
                        return 单元格边框类型.中号点点划线边框;
                    case BorderStyle.SlantedDashDot:
                        return 单元格边框类型.斜点划线边框;
                    default:
                        return 单元格边框类型.无边框;
                }
            }
        }

        public 单元格样式 置单元格右边框类型(单元格边框类型 newBorderStyle)
        {
            switch (newBorderStyle)
            {
                case 单元格边框类型.无边框:
                    _样式.BorderRight = BorderStyle.None;
                    break;
                case 单元格边框类型.细边框:
                    _样式.BorderRight = BorderStyle.Thin;
                    break;
                case 单元格边框类型.中号边框:
                    _样式.BorderRight = BorderStyle.Medium;
                    break;
                case 单元格边框类型.划线边框:
                    _样式.BorderRight = BorderStyle.Dashed;
                    break;
                case 单元格边框类型.点线边框:
                    _样式.BorderRight = BorderStyle.Dotted;
                    break;
                case 单元格边框类型.厚边框:
                    _样式.BorderRight = BorderStyle.Thick;
                    break;
                case 单元格边框类型.双线边框:
                    _样式.BorderRight = BorderStyle.Double;
                    break;
                case 单元格边框类型.发宽边框:
                    _样式.BorderRight = BorderStyle.Hair;
                    break;
                case 单元格边框类型.中号划线边框:
                    _样式.BorderRight = BorderStyle.MediumDashed;
                    break;
                case 单元格边框类型.点划线边框:
                    _样式.BorderRight = BorderStyle.DashDot;
                    break;
                case 单元格边框类型.中号点划线边框:
                    _样式.BorderRight = BorderStyle.MediumDashDot;
                    break;
                case 单元格边框类型.点点划线边框:
                    _样式.BorderRight = BorderStyle.DashDotDot;
                    break;
                case 单元格边框类型.中号点点划线边框:
                    _样式.BorderRight = BorderStyle.MediumDashDotDot;
                    break;
                case 单元格边框类型.斜点划线边框:
                    _样式.BorderRight = BorderStyle.SlantedDashDot;
                    break;
                default:
                    _样式.BorderRight = BorderStyle.Thin;
                    break;
            }
            return this;
        }

        public 单元格边框类型 单元格右边框类型
        {
            get
            {
                switch (_样式.BorderRight)
                {
                    case BorderStyle.None:
                        return 单元格边框类型.无边框;
                    case BorderStyle.Thin:
                        return 单元格边框类型.细边框;
                    case BorderStyle.Medium:
                        return 单元格边框类型.中号边框;
                    case BorderStyle.Dashed:
                        return 单元格边框类型.划线边框;
                    case BorderStyle.Dotted:
                        return 单元格边框类型.点线边框;
                    case BorderStyle.Thick:
                        return 单元格边框类型.厚边框;
                    case BorderStyle.Double:
                        return 单元格边框类型.双线边框;
                    case BorderStyle.Hair:
                        return 单元格边框类型.发宽边框;
                    case BorderStyle.MediumDashed:
                        return 单元格边框类型.中号划线边框;
                    case BorderStyle.DashDot:
                        return 单元格边框类型.点划线边框;
                    case BorderStyle.MediumDashDot:
                        return 单元格边框类型.中号点划线边框;
                    case BorderStyle.DashDotDot:
                        return 单元格边框类型.点点划线边框;
                    case BorderStyle.MediumDashDotDot:
                        return 单元格边框类型.中号点点划线边框;
                    case BorderStyle.SlantedDashDot:
                        return 单元格边框类型.斜点划线边框;
                    default:
                        return 单元格边框类型.无边框;
                }
            }
        }

        public 单元格样式 置单元格下边框类型(单元格边框类型 newBorderStyle)
        {

            switch (newBorderStyle)
            {
                case 单元格边框类型.无边框:
                    _样式.BorderBottom = BorderStyle.None;
                    break;
                case 单元格边框类型.细边框:
                    _样式.BorderBottom = BorderStyle.Thin;
                    break;
                case 单元格边框类型.中号边框:
                    _样式.BorderBottom = BorderStyle.Medium;
                    break;
                case 单元格边框类型.划线边框:
                    _样式.BorderBottom = BorderStyle.Dashed;
                    break;
                case 单元格边框类型.点线边框:
                    _样式.BorderBottom = BorderStyle.Dotted;
                    break;
                case 单元格边框类型.厚边框:
                    _样式.BorderBottom = BorderStyle.Thick;
                    break;
                case 单元格边框类型.双线边框:
                    _样式.BorderBottom = BorderStyle.Double;
                    break;
                case 单元格边框类型.发宽边框:
                    _样式.BorderBottom = BorderStyle.Hair;
                    break;
                case 单元格边框类型.中号划线边框:
                    _样式.BorderBottom = BorderStyle.MediumDashed;
                    break;
                case 单元格边框类型.点划线边框:
                    _样式.BorderBottom = BorderStyle.DashDot;
                    break;
                case 单元格边框类型.中号点划线边框:
                    _样式.BorderBottom = BorderStyle.MediumDashDot;
                    break;
                case 单元格边框类型.点点划线边框:
                    _样式.BorderBottom = BorderStyle.DashDotDot;
                    break;
                case 单元格边框类型.中号点点划线边框:
                    _样式.BorderBottom = BorderStyle.MediumDashDotDot;
                    break;
                case 单元格边框类型.斜点划线边框:
                    _样式.BorderBottom = BorderStyle.SlantedDashDot;
                    break;
                default:
                    _样式.BorderBottom = BorderStyle.Thin;
                    break;
            }
            return this;
        }

        public 单元格边框类型 单元格下边框类型
        {
            get
            {
                switch (_样式.BorderBottom)
                {
                    case BorderStyle.None:
                        return 单元格边框类型.无边框;
                    case BorderStyle.Thin:
                        return 单元格边框类型.细边框;
                    case BorderStyle.Medium:
                        return 单元格边框类型.中号边框;
                    case BorderStyle.Dashed:
                        return 单元格边框类型.划线边框;
                    case BorderStyle.Dotted:
                        return 单元格边框类型.点线边框;
                    case BorderStyle.Thick:
                        return 单元格边框类型.厚边框;
                    case BorderStyle.Double:
                        return 单元格边框类型.双线边框;
                    case BorderStyle.Hair:
                        return 单元格边框类型.发宽边框;
                    case BorderStyle.MediumDashed:
                        return 单元格边框类型.中号划线边框;
                    case BorderStyle.DashDot:
                        return 单元格边框类型.点划线边框;
                    case BorderStyle.MediumDashDot:
                        return 单元格边框类型.中号点划线边框;
                    case BorderStyle.DashDotDot:
                        return 单元格边框类型.点点划线边框;
                    case BorderStyle.MediumDashDotDot:
                        return 单元格边框类型.中号点点划线边框;
                    case BorderStyle.SlantedDashDot:
                        return 单元格边框类型.斜点划线边框;
                    default:
                        return 单元格边框类型.无边框;
                }
            }
        }

        public 单元格样式 置单元格左边框色(int colorIndex)
        {
            _样式.LeftBorderColor = (short)colorIndex;
            return this;
        }

        public 单元格色彩标号 单元格左边框色
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_样式.LeftBorderColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.黑色;
            }
        }

        public 单元格样式 置单元格左边框色(单元格色彩标号 color)
        {
            _样式.LeftBorderColor = (short)color;
            return this;
        }

        public 单元格样式 置单元格上边框色(int colorIndex)
        {
            _样式.TopBorderColor = (short)colorIndex;
            return this;
        }

        public 单元格色彩标号 单元格上边框色
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_样式.TopBorderColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.黑色;
            }
        }

        public 单元格样式 置单元格上边框色(单元格色彩标号 color)
        {
            _样式.TopBorderColor = (short)color;
            return this;
        }

        public 单元格样式 置单元格右边框色(int colorIndex)
        {
            _样式.RightBorderColor = (short)colorIndex;
            return this;
        }

        public 单元格色彩标号 单元格右边框色
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_样式.RightBorderColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.黑色;
            }
        }

        public 单元格样式 置单元格右边框色(单元格色彩标号 color)
        {
            _样式.RightBorderColor = (short)color;
            return this;
        }

        public 单元格样式 置单元格下边框色(int colorIndex)
        {
            _样式.BottomBorderColor = (short)colorIndex;
            return this;
        }

        public 单元格色彩标号 单元格下边框色
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_样式.BottomBorderColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.黑色;
            }
        }

        public 单元格样式 置单元格下边框色(单元格色彩标号 color)
        {
            _样式.BottomBorderColor = (short)color;
            return this;
        }

        public 单元格样式 置单元格前景色(单元格色彩标号 color)
        {
            if (this.单元格字体 != null) this.单元格字体.置单元格文本色彩(color);
            return this;
        }

        public 单元格样式 置单元格背景色(单元格色彩标号 color)
        {
            var colorIndex = (short)color;
            置单元格背景色(colorIndex);
            return this;
        }

        public 单元格色彩标号 单元格背景色
        {
            get
            {
                if (_样式.FillPattern != FillPattern.SolidForeground) return 单元格色彩标号.白色;

                if (Enum.TryParse<单元格色彩标号>(_样式.FillBackgroundColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.白色;
            }
        }

        public 单元格样式 置单元格背景色(int colorIndex)
        {
            _样式.FillPattern = FillPattern.SolidForeground;
            _样式.FillForegroundColor = (short)colorIndex;
            return this;
        }

        public 单元格样式 置单元格背景图形(FillPattern pattern)
        {
            _样式.FillPattern = pattern;
            return this;
        }

        public 单元格样式 置单元格背景图形(int index)
        {
            if (index < 0) index = 0;

            if (index > 18) index = 18;

            if (Enum.TryParse<FillPattern>(index.ToString(), out FillPattern pattern))
            {
                _样式.FillPattern = pattern;
            }
            return this;
        }

        public int 单元格背景图形索引 { get { return (int)_样式.FillPattern; } }

        public 单元格样式 置单元格背景图形(单元格背景图形 pattern)
        {
            return 置单元格背景图形((int)pattern);
        }

        public 单元格样式 置单元格背景图形色彩(单元格色彩标号 color)
        {
            _样式.FillForegroundColor = (short)color;
            return this;
        }

        public 单元格色彩标号 单元格背景图形
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_样式.FillForegroundColor.ToString(), true, out 单元格色彩标号 result))
                {
                    return result;
                }

                return 单元格色彩标号.黑色;
            }
        }

        public 单元格样式 置单元格背景图形色彩(int colorIndex)
        {
            if (colorIndex < 8) colorIndex = 8;

            if (colorIndex > 64) colorIndex = 64;

            _样式.FillForegroundColor = (short)colorIndex;
            return this;
        }

        public 单元格样式 置单元格字体(单元格字体 font)
        {
            _样式.SetFont(font.字体);
            _单元格字体 = font;
            return this;
        }

        private 单元格字体 _单元格字体;

        public 单元格字体 单元格字体 { get { return _单元格字体; } }

        public 单元格样式 置单元格缩小字体填充(bool shrinkToFit = true)
        {
            _样式.ShrinkToFit = shrinkToFit;
            return this;
        }

        public bool 单元格缩小字体填充 { get { return _样式.ShrinkToFit; } }
    }

    public class 单元格字体
    {
        internal 单元格字体(IFont font)
        {
            _字体 = font;
        }

        private IFont _字体;

        public IFont 字体 { get => _字体; }

        public 单元格字体 置单元格下划线类型(单元格下划线类型 underline = 单元格下划线类型.单下划线)
        {
            switch (underline)
            {
                case 单元格下划线类型.无下划线:
                    _字体.Underline = FontUnderlineType.None;
                    break;
                case 单元格下划线类型.单下划线:
                    _字体.Underline = FontUnderlineType.Single;
                    break;
                case 单元格下划线类型.双下划线:
                    _字体.Underline = FontUnderlineType.Double;
                    break;
                case 单元格下划线类型.会计用单下划线:
                    _字体.Underline = FontUnderlineType.SingleAccounting;
                    break;
                case 单元格下划线类型.会计用双下划线:
                    _字体.Underline = FontUnderlineType.DoubleAccounting;
                    break;
            }
            return this;
        }

        public 单元格下划线类型 单元格下划线类型
        {
            get
            {
                switch (_字体.Underline)
                {
                    case FontUnderlineType.Single: return 单元格下划线类型.单下划线;
                    case FontUnderlineType.Double: return 单元格下划线类型.双下划线;
                    case FontUnderlineType.SingleAccounting: return 单元格下划线类型.会计用单下划线;
                    case FontUnderlineType.DoubleAccounting: return 单元格下划线类型.会计用双下划线;
                    default: return 单元格下划线类型.无下划线;
                }
            }
        }

        public 单元格字体 置单元格加粗(bool bold = true)
        {
            _字体.IsBold = bold;
            return this;
        }

        public bool 单元格加粗 { get { return _字体.IsBold; } }

        public 单元格字体 置单元格倾斜(bool italic = true)
        {
            _字体.IsItalic = italic;
            return this;
        }

        public bool 单元格倾斜 { get { return _字体.IsItalic; } }

        public 单元格字体 置单元格删除线(bool strike = true)
        {
            _字体.IsStrikeout = strike;
            return this;
        }

        public bool 单元格删除线 { get { return _字体.IsStrikeout; } }

        public 单元格字体 置单元格文本色彩(单元格色彩标号 color = 单元格色彩标号.红色)
        {
            _字体.Color = (short)color;
            return this;
        }

        public 单元格色彩标号 单元格文本色彩标号
        {
            get
            {
                if (Enum.TryParse<单元格色彩标号>(_字体.Color.ToString(), out 单元格色彩标号 result))
                {
                    return result;
                }
                else return 单元格色彩标号.黑色;
            }
        }

        public 单元格字体 置单元格字体名(string fontName)
        {
            _字体.FontName = fontName;
            return this;
        }

        public string 单元格字体名 { get { return _字体.FontName; } }

        /// <summary>
        /// 设置单元格字号。（单位为缇，即 1/20 个 Point（点、磅））
        /// </summary>
        /// <param name="fontSize">1缇等于1/1440英寸或1/567厘米。</param>
        /// <returns></returns>
        public 单元格字体 置单元格字号缇数(double fontSize = 220)
        {
            _字体.FontHeight = fontSize;
            return this;
        }

        public double 单元格字号缇数 { get { return _字体.FontHeight; } }

        /// <summary>
        /// 置单元格字号。（单位是磅（或点），一磅是 1/72 英寸）
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public 单元格字体 置单元格字号点数(double points = 11)
        {
            _字体.FontHeightInPoints = points;
            return this;
        }

        public double 单元格字号点数 { get { return _字体.FontHeightInPoints; } }

        /// <summary>
        /// 置单元格字号。（单位是磅（或点），一磅是 1/72 英寸）
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public 单元格字体 置单元格字号磅数(double points = 11)
        {
            _字体.FontHeightInPoints = points;
            return this;
        }

        public double 单元格字号磅数 { get { return _字体.FontHeightInPoints; } }

        /// <summary>
        /// 置单元格字号。（单位是磅（或点），一磅是 1/72 英寸）
        /// 此方法默认等同于“置单元格字号点数”方法。
        /// </summary>
        /// <param name="points">字号点数。</param>
        /// <returns></returns>
        public 单元格字体 置单元格字号(double points)
        {
            _字体.FontHeightInPoints = points;
            return this;
        }

        public double 单元格字号 { get { return _字体.FontHeightInPoints; } }

        public 单元格字体 置单元格上下标(单元格上下标类型 type = 单元格上下标类型.上标文本)
        {
            _字体.TypeOffset = (FontSuperScript)type;
            return this;
        }

        public 单元格上下标类型 单元格上下标
        {
            get
            {
                return (单元格上下标类型)_字体.TypeOffset;
            }
        }
    }

    public enum 单元格类型
    {
        文本单元格 = CellType.String,
        逻辑单元格 = CellType.Boolean,
        空单元格 = CellType.Blank,
        错误单元格 = CellType.Error,
        公式单元格 = CellType.Formula,
        数字单元格 = CellType.Numeric,
        未知类型单元格 = CellType.Unknown
    }

    public enum 单元格下划线类型
    {
        无下划线 = FontUnderlineType.None,
        单下划线 = FontUnderlineType.Single,
        双下划线 = FontUnderlineType.Double,
        会计用单下划线 = FontUnderlineType.SingleAccounting,
        会计用双下划线 = FontUnderlineType.DoubleAccounting,
    }

    public enum 单元格上下标类型
    {
        普通文本 = FontSuperScript.None,
        上标文本 = FontSuperScript.Super,
        下标文本 = FontSuperScript.Sub,
    }

    public enum 单元格背景图形
    {
        无填充图形 = NPOI.SS.UserModel.FillPattern.NoFill,
        纯色背景 = NPOI.SS.UserModel.FillPattern.SolidForeground,
        点图 = NPOI.SS.UserModel.FillPattern.FineDots,
        斜线 = NPOI.SS.UserModel.FillPattern.AltBars,
        散点 = NPOI.SS.UserModel.FillPattern.SparseDots,
        宽横线 = NPOI.SS.UserModel.FillPattern.ThickHorizontalBands,
        宽竖线 = NPOI.SS.UserModel.FillPattern.ThickVerticalBands,
        宽反对角线 = NPOI.SS.UserModel.FillPattern.ThickBackwardDiagonals,
        宽对角线 = NPOI.SS.UserModel.FillPattern.ThickForwardDiagonals,
        大斑点 = NPOI.SS.UserModel.FillPattern.BigSpots,
        砖块 = NPOI.SS.UserModel.FillPattern.Bricks,
        细横线 = NPOI.SS.UserModel.FillPattern.ThinHorizontalBands,
        细竖线 = NPOI.SS.UserModel.FillPattern.ThinVerticalBands,
        细反对角线 = NPOI.SS.UserModel.FillPattern.ThinBackwardDiagonals,
        细对角线 = NPOI.SS.UserModel.FillPattern.ThinForwardDiagonals,
        方形 = NPOI.SS.UserModel.FillPattern.Squares,
        菱形 = NPOI.SS.UserModel.FillPattern.Diamonds,
        较少的点 = NPOI.SS.UserModel.FillPattern.LessDots,
        最少的点 = NPOI.SS.UserModel.FillPattern.LeastDots
    }

    public class 区域
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="regionMark"></param>
        public 区域(string regionMark)
        {
            if (string.IsNullOrWhiteSpace(regionMark))
            {
                _区域体 = new CellRangeAddress(0, 0, 0, 0);
                return;
            }

            var reg = new Regex(@"[a-zA-Z]{1,3}\d+[:：][a-zA-Z]{1,3}\d+");
            if (reg.Match(regionMark).Success == false)
            {
                _区域体 = new CellRangeAddress(0, 0, 0, 0);
                return;
            }

            var pieces = regionMark.Split(new char[] { ':', '：' });
            if (pieces.Length != 2)
            {
                _区域体 = new CellRangeAddress(0, 0, 0, 0);
                return;
            }

            var leftTopCellRef = new CellReference(pieces[0]);
            var rightBottomCellRef = new CellReference(pieces[1]);

            _区域体 = new CellRangeAddress(Math.Min(leftTopCellRef.Row, rightBottomCellRef.Row), Math.Max(leftTopCellRef.Row, rightBottomCellRef.Row),
                Math.Min(leftTopCellRef.Col, rightBottomCellRef.Col), Math.Max(leftTopCellRef.Col, rightBottomCellRef.Col));
        }

        public 区域(int fstRow, int lstRow, int fstCol, int lstCol)
        {
            if (fstRow < 0) fstRow = 0; if (fstRow > 1048575) fstRow = 1048575;
            if (lstRow < 0) lstRow = 0; if (lstRow > 1048575) lstRow = 1048575;
            if (fstCol < 0) fstCol = 0; if (fstCol > 16383) fstCol = 16383;
            if (lstCol < 0) lstCol = 0; if (lstCol > 16383) lstCol = 16383;

            _区域体 = new CellRangeAddress(Math.Min(fstRow, lstRow), Math.Max(fstRow, lstRow), Math.Min(fstCol, lstCol), Math.Max(fstCol, lstCol));
        }

        private CellRangeAddress _区域体;

        public CellRangeAddress 区域体
        {
            get { return _区域体; }
        }

        public override string ToString()
        {
            if (_区域体 == null) return null;

            return $"FirstRow:{_区域体.FirstRow};LastRow:{_区域体.LastRow};FirstColumn:{_区域体.FirstColumn};LastColumn:{_区域体.LastColumn}";
        }

        public int 首行索引
        {
            get
            {
                return _区域体 == null ? -1 : _区域体.FirstRow;
            }
            set
            {
                if (_区域体 != null) _区域体.FirstRow = value;
            }
        }
        public int 尾行索引
        {
            get
            {
                return _区域体 == null ? -1 : _区域体.LastRow;
            }
            set
            {
                if (_区域体 != null) _区域体.LastRow = value;
            }
        }
        public int 首列索引
        {
            get
            {
                return _区域体 == null ? -1 : _区域体.FirstColumn;
            }
            set
            {
                if (_区域体 != null) _区域体.FirstColumn = value;
            }
        }
        public int 尾列索引
        {
            get
            {
                return _区域体 == null ? -1 : _区域体.LastColumn;
            }
            set
            {
                if (_区域体 != null) _区域体.LastColumn = value;
            }
        }
    }

    public enum 单元格色彩标号
    {
        湖绿色 = HSSFColor.Aqua.Index,
        自动 = HSSFColor.Automatic.Index,
        黑色 = HSSFColor.Black.Index,
        蓝色 = HSSFColor.Blue.Index,
        蓝灰色 = HSSFColor.BlueGrey.Index,
        亮绿色 = HSSFColor.BrightGreen.Index,
        棕色 = HSSFColor.Brown.Index,
        珊瑚色 = HSSFColor.Coral.Index,
        珊瑚蓝 = HSSFColor.CornflowerBlue.Index,
        深蓝色 = HSSFColor.DarkBlue.Index,
        深绿色 = HSSFColor.DarkGreen.Index,
        深红色 = HSSFColor.DarkRed.Index,
        深青色 = HSSFColor.DarkTeal.Index,
        深黄色 = HSSFColor.DarkYellow.Index,
        金色 = HSSFColor.Gold.Index,
        绿色 = HSSFColor.Green.Index,
        二十五灰色 = HSSFColor.Grey25Percent.Index,
        四十灰色 = HSSFColor.Grey40Percent.Index,
        五十灰色 = HSSFColor.Grey50Percent.Index,
        八十灰色 = HSSFColor.Grey80Percent.Index,
        靛蓝 = HSSFColor.Indigo.Index,
        薰衣草 = HSSFColor.Lavender.Index,
        柠檬雪纺 = HSSFColor.LemonChiffon.Index,
        浅蓝色 = HSSFColor.LightBlue.Index,
        浅珊瑚蓝 = HSSFColor.LightCornflowerBlue.Index,
        浅绿色 = HSSFColor.LightGreen.Index,
        浅橙色 = HSSFColor.LightOrange.Index,
        浅绿松石 = HSSFColor.LightTurquoise.Index,
        浅黄色 = HSSFColor.LightYellow.Index,
        石灰 = HSSFColor.Lime.Index,
        栗色 = HSSFColor.Maroon.Index,
        橄榄绿 = HSSFColor.OliveGreen.Index,
        橙色 = HSSFColor.Orange.Index,
        兰花 = HSSFColor.Orchid.Index,
        淡蓝色 = HSSFColor.PaleBlue.Index,
        粉红色 = HSSFColor.Pink.Index,
        李子 = HSSFColor.Plum.Index,
        红色 = HSSFColor.Red.Index,
        玫瑰 = HSSFColor.Rose.Index,
        宝蓝 = HSSFColor.RoyalBlue.Index,
        海绿 = HSSFColor.SeaGreen.Index,
        天蓝色 = HSSFColor.SkyBlue.Index,
        棕褐色 = HSSFColor.Tan.Index,
        青色 = HSSFColor.Teal.Index,
        绿松石 = HSSFColor.Turquoise.Index,
        紫色 = HSSFColor.Violet.Index,
        白色 = HSSFColor.White.Index,
        黄色 = HSSFColor.Yellow.Index,
    }

    public enum 色彩标号
    {
        湖绿色 = HSSFColor.Aqua.Index,
        自动 = HSSFColor.Automatic.Index,
        黑色 = HSSFColor.Black.Index,
        蓝色 = HSSFColor.Blue.Index,
        蓝灰色 = HSSFColor.BlueGrey.Index,
        亮绿色 = HSSFColor.BrightGreen.Index,
        棕色 = HSSFColor.Brown.Index,
        珊瑚色 = HSSFColor.Coral.Index,
        珊瑚蓝 = HSSFColor.CornflowerBlue.Index,
        深蓝色 = HSSFColor.DarkBlue.Index,
        深绿色 = HSSFColor.DarkGreen.Index,
        深红色 = HSSFColor.DarkRed.Index,
        深青色 = HSSFColor.DarkTeal.Index,
        深黄色 = HSSFColor.DarkYellow.Index,
        金色 = HSSFColor.Gold.Index,
        绿色 = HSSFColor.Green.Index,
        二十五灰色 = HSSFColor.Grey25Percent.Index,
        四十灰色 = HSSFColor.Grey40Percent.Index,
        五十灰色 = HSSFColor.Grey50Percent.Index,
        八十灰色 = HSSFColor.Grey80Percent.Index,
        靛蓝 = HSSFColor.Indigo.Index,
        薰衣草 = HSSFColor.Lavender.Index,
        柠檬雪纺 = HSSFColor.LemonChiffon.Index,
        浅蓝色 = HSSFColor.LightBlue.Index,
        浅珊瑚蓝 = HSSFColor.LightCornflowerBlue.Index,
        浅绿色 = HSSFColor.LightGreen.Index,
        浅橙色 = HSSFColor.LightOrange.Index,
        浅绿松石 = HSSFColor.LightTurquoise.Index,
        浅黄色 = HSSFColor.LightYellow.Index,
        石灰 = HSSFColor.Lime.Index,
        栗色 = HSSFColor.Maroon.Index,
        橄榄绿 = HSSFColor.OliveGreen.Index,
        橙色 = HSSFColor.Orange.Index,
        兰花 = HSSFColor.Orchid.Index,
        淡蓝色 = HSSFColor.PaleBlue.Index,
        粉红色 = HSSFColor.Pink.Index,
        李子 = HSSFColor.Plum.Index,
        红色 = HSSFColor.Red.Index,
        玫瑰 = HSSFColor.Rose.Index,
        宝蓝 = HSSFColor.RoyalBlue.Index,
        海绿 = HSSFColor.SeaGreen.Index,
        天蓝色 = HSSFColor.SkyBlue.Index,
        棕褐色 = HSSFColor.Tan.Index,
        青色 = HSSFColor.Teal.Index,
        绿松石 = HSSFColor.Turquoise.Index,
        紫色 = HSSFColor.Violet.Index,
        白色 = HSSFColor.White.Index,
        黄色 = HSSFColor.Yellow.Index,
    }

    public enum 单元格边框类型
    {
        无边框 = BorderStyle.None,
        细边框 = BorderStyle.Thin,
        中号边框 = BorderStyle.Medium,
        划线边框 = BorderStyle.Dashed,
        点线边框 = BorderStyle.Dotted,
        厚边框 = BorderStyle.Thick,
        双线边框 = BorderStyle.Double,
        发宽边框 = BorderStyle.Hair,
        中号划线边框 = BorderStyle.MediumDashed,
        点划线边框 = BorderStyle.DashDot,
        中号点划线边框 = BorderStyle.MediumDashDot,
        点点划线边框 = BorderStyle.DashDotDot,
        中号点点划线边框 = BorderStyle.MediumDashDotDot,
        斜点划线边框 = BorderStyle.SlantedDashDot,
    }

    public enum 单元格水平对齐
    {
        水平通用 = NPOI.SS.UserModel.HorizontalAlignment.General,
        水平居左 = NPOI.SS.UserModel.HorizontalAlignment.Left,
        水平居中 = NPOI.SS.UserModel.HorizontalAlignment.Center,
        水平居右 = NPOI.SS.UserModel.HorizontalAlignment.Right,
        水平填充 = NPOI.SS.UserModel.HorizontalAlignment.Fill,
        水平两端 = NPOI.SS.UserModel.HorizontalAlignment.Justify,
        水平跨列居中 = NPOI.SS.UserModel.HorizontalAlignment.CenterSelection,
        水平分散 = NPOI.SS.UserModel.HorizontalAlignment.Distributed,
    }

    public enum 单元格垂直对齐
    {
        垂直无 = NPOI.SS.UserModel.VerticalAlignment.None,
        垂直靠上 = NPOI.SS.UserModel.VerticalAlignment.Top,
        垂直居中 = NPOI.SS.UserModel.VerticalAlignment.Center,
        垂直靠下 = NPOI.SS.UserModel.VerticalAlignment.Bottom,
        垂直两端 = NPOI.SS.UserModel.VerticalAlignment.Justify,
        垂直分散 = NPOI.SS.UserModel.VerticalAlignment.Distributed,
    }

    public class 单元格数据格式
    {
        public static short 取内置格式索引(string partten)
        {
            return HSSFDataFormat.GetBuiltinFormat(partten);
        }

        public static string 取内置格式(int index)
        {
            return HSSFDataFormat.GetBuiltinFormats()[index];
        }
    }

    public enum 工作表页面尺寸
    {
        打印机默认尺寸 = NPOI.SS.UserModel.PaperSize.PRINTER_DEFAULT_PAPERSIZE,
        美式小信封 = NPOI.SS.UserModel.PaperSize.US_Letter_Small,
        美式小报 = NPOI.SS.UserModel.PaperSize.US_Tabloid,
        美式总账 = NPOI.SS.UserModel.PaperSize.US_Ledger,
        美式法律文书 = NPOI.SS.UserModel.PaperSize.US_Legal,
        美式报告单 = NPOI.SS.UserModel.PaperSize.US_Statement,
        美式行政文书 = NPOI.SS.UserModel.PaperSize.US_Executive,
        A3 = NPOI.SS.UserModel.PaperSize.A3,
        A4 = NPOI.SS.UserModel.PaperSize.A4,
        小A4 = NPOI.SS.UserModel.PaperSize.A4_Small,
        A5 = NPOI.SS.UserModel.PaperSize.A5,
        B4 = NPOI.SS.UserModel.PaperSize.B4,
        B5 = NPOI.SS.UserModel.PaperSize.B5,
        对开 = NPOI.SS.UserModel.PaperSize.Folio,
        四开 = NPOI.SS.UserModel.PaperSize.Quarto,
        十乘十四 = NPOI.SS.UserModel.PaperSize.TEN_BY_FOURTEEN,
        十一乘十七 = NPOI.SS.UserModel.PaperSize.ELEVEN_BY_SEVENTEEN,
        美式笔记 = NPOI.SS.UserModel.PaperSize.US_Note,
        美式九号信封 = NPOI.SS.UserModel.PaperSize.US_Envelope_9,
        美式十号信封 = NPOI.SS.UserModel.PaperSize.US_Envelope_10,
        美式十一号信封 = NPOI.SS.UserModel.PaperSize.US_Envelope_11,
        美式十二号信封 = NPOI.SS.UserModel.PaperSize.US_Envelope_12,
        美式十四号信封 = NPOI.SS.UserModel.PaperSize.US_Envelope_14,
        C号表 = NPOI.SS.UserModel.PaperSize.C_Size_Sheet,
        D号表 = NPOI.SS.UserModel.PaperSize.D_Size_Sheet,
        E号表 = NPOI.SS.UserModel.PaperSize.E_Size_Sheet,
        DL信封 = NPOI.SS.UserModel.PaperSize.Envelope_DL,
        C5信封 = NPOI.SS.UserModel.PaperSize.Envelope_C5,
        C3信封 = NPOI.SS.UserModel.PaperSize.Envelope_C3,
        C4信封 = NPOI.SS.UserModel.PaperSize.Envelope_C4,
        C6信封 = NPOI.SS.UserModel.PaperSize.Envelope_C6,
        大信封 = NPOI.SS.UserModel.PaperSize.Envelope_MONARCH,
        A4扩大 = NPOI.SS.UserModel.PaperSize.A4_EXTRA,
        A4横向 = NPOI.SS.UserModel.PaperSize.A4_TRANSVERSE_PAPERSIZE,  // A4 Transverse - 210x297 mm
        A4增强 = NPOI.SS.UserModel.PaperSize.A4_PLUS_PAPERSIZE,      // A4 Plus - 210x330 mm
        美式旋转信封 = NPOI.SS.UserModel.PaperSize.LETTER_ROTATED_PAPERSIZE,   // US Letter Rotated 11 x 8 1/2 in
        A4旋转 = NPOI.SS.UserModel.PaperSize.A4_ROTATED_PAPERSIZE,       //A4 Rotated - 297x210 mm
    }

    public enum 纸张类型
    {
        PaperLetter = 1,
        PaperLegal = 5,
        PaperExecutive = 7,
        PaperA4 = 9,
        PaperA5 = 11,
        Paper10号信封 = 20,
        PaperDL信封 = 27,
        PaperC5信封 = 28,
        PaperB5信封 = 34,
        PaperMonarch信封 = 37,
        PaperB5JIS = 13,
        PaperB5 = 259,
        PaperB5ISO = 259,
        PaperA6 = 262,
        Paper双面明信片 = 261,
        Paper明信片 = 260,
        Paper8513 = 258,
        Paper16K = 257,
    }

    #endregion

    public class 文件
    {
        public 文件(string fullPath)
        {
            _文件路径 = fullPath;
        }

        private string _文件路径;
        /// <summary>
        /// 这个属性名与其它类有重名，不好用。为保持旧代码兼容，保留，但不再提示。
        /// </summary>
        public string 文件路径
        {
            get { return _文件路径; }
        }

        public string 完整路径
        {
            get { return _文件路径; }
        }

        public FileInfo 信息
        {
            get
            {
                try
                {
                    var info = new FileInfo(_文件路径);
                    if (info != null && info.Exists) return info;

                    return null;
                }
                catch { return null; }
            }
        }

        public string 后缀名
        {
            get
            {
                var fi = 信息;
                if (fi == null) return "";

                return "." + fi.Extension.TrimStart(new char[] { ' ', '　', '\t', '.' });
            }
        }

        public string 目录路径
        {
            get
            {
                var info = 信息;
                if (info == null || info.Directory == null) return null;

                return info.Directory.FullName;
            }
        }

        public string 短名
        {
            get
            {
                var info = 信息;
                return info.Name;
            }
        }

        public string 文件短名
        {
            get => 短名;
        }

        public string 无后缀文件名
        {
            get
            {
                var info = 信息;
                var suffix = 后缀名;
                if (string.IsNullOrEmpty(suffix))
                    return info.Name;

                return info.Name.Substring(0, info.Name.Length - 后缀名.Length);
            }
        }

        public bool 是否存在
        {
            get { return 文件已存在(this._文件路径); }
        }

        public static bool 文件已存在(string filePath)
        {
            return File.Exists(filePath);
        }

        public static bool 目录已存在(string dirPath)
        {
            return Directory.Exists(dirPath);
        }

        public static DirectoryInfo 创建目录(string dirPath)
        {
            return Directory.CreateDirectory(dirPath);
        }

        public 文件 打开()
        {
            打开(this._文件路径);
            return this;
        }

        public 文件 打开自身()
        {
            if (是否存在 == false)
                throw new Exception("指定文件不存在。");

            打开(this._文件路径);
            return this;
        }

        public static void 打开(string fullPath)
        {
            var info = new 文件(fullPath);

            if (info.是否存在 == false)
                throw new Exception("指定文件不存在。");

            if (info != null && info.信息 != null)
            {
                System.Diagnostics.Process.Start(info.信息.FullName);
            }
            else
            {
                LMessageBox.ShowWarning("指定路径错误！");
            }
        }

        public static void 打开指定文件(string fullPath)
        {
            文件.打开(fullPath);
        }

        public static IronPython.Runtime.PythonList 筛选(string dirPath, string pattern = "*", bool ignoreCase = true)
        {
            var di = new DirectoryInfo(dirPath);
            if (di.Exists == false)
                throw new Exception("目录不存在。");

            var list = new IronPython.Runtime.PythonList();

            var entries = di.GetFiles(pattern, System.IO.SearchOption.TopDirectoryOnly);
            foreach (var entry in entries)
            {
                list.append(entry.FullName);
            }

            return list;
        }

        public 文件 复制(string destFilePath)
        {
            if (File.Exists(this._文件路径) == false)
                throw new Exception("源文件不存在！");

            var info = new FileInfo(destFilePath);
            if (info != null && System.IO.File.Exists(this._文件路径))
            {
                复制(this._文件路径, destFilePath);
            }
            else
            {
                throw new Exception("目标路径非法！");
            }
            return this;
        }

        public static void 复制(string srcFilePath, string destFilePath)
        {
            var srcInfo = new FileInfo(srcFilePath);
            var destInfo = new FileInfo(destFilePath);
            if (srcInfo.Exists == false)
                throw new Exception("源文件不存在!");
            if (destInfo.Directory.Exists == false)
            {
                destInfo.Directory.Create();
            }

            System.IO.File.Copy(srcFilePath, destFilePath);
        }

        public 文件 移动(string destFilePath)
        {
            if (File.Exists(this._文件路径) == false)
                throw new Exception("源文件不存在！");

            var info = new FileInfo(this._文件路径);
            if (info != null && System.IO.File.Exists(this._文件路径) && LFile.IsValidFilePath(destFilePath, false))
            {
                var destFileInfo = new FileInfo(destFilePath);
                if (destFileInfo.Directory.Exists == false)
                {
                    System.IO.Directory.CreateDirectory(destFileInfo.Directory.FullName);
                }
                info.MoveTo(destFilePath);
                // 移动(this._文件路径, destFilePath); // 已知调用这个会出错。
                // this._文件路径 = destFilePath;
                // 这里不适合更改
            }
            else
            {
                throw new Exception("目标路径非法！");
            }
            return this;
        }

        public static void 移动(string srcFilePath, string destFilePath)
        {
            var srcInfo = new FileInfo(srcFilePath);
            var destInfo = new FileInfo(destFilePath);
            if (srcInfo.Exists == false)
                throw new Exception("源文件不存在!");
            if (destInfo.Directory.Exists == false)
            {
                destInfo.Directory.Create();
            }

            System.IO.File.Move(srcFilePath, destFilePath);
        }

        public 文件 删除()
        {
            if (File.Exists(this._文件路径) == false)
                throw new Exception("源文件不存在！");

            删除(this._文件路径);
            return this;
        }

        public 文件 删除到回收站()
        {
            if (File.Exists(this._文件路径) == false)
                throw new Exception("源文件不存在！");

            删除到回收站(this._文件路径);
            return this;
        }

        public static void 删除(string srcFilePath)
        {
            var srcInfo = new FileInfo(srcFilePath);
            if (srcInfo.Exists == false)
                throw new Exception("源文件不存在!");

            System.IO.File.Delete(srcFilePath);
        }

        public static void 删除到回收站(string srcFilePath)
        {
            var srcInfo = new FileInfo(srcFilePath);
            if (srcInfo.Exists == false)
                throw new Exception("源文件不存在!");

            FileSystem.DeleteFile(srcFilePath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
        }

        public static void 删除目录(string dirPath, bool recursive = false)
        {
            var di = new DirectoryInfo(dirPath);
            if (di.Exists == false)
                throw new Exception("目录不存在!");

            System.IO.Directory.Delete(dirPath, recursive);
        }

        public static void 删除目录到回收站(string dirPath, bool recursive = false)
        {
            var di = new DirectoryInfo(dirPath);
            if (di.Exists == false)
                throw new Exception("目录不存在!");

            if (recursive)
            {
                FileSystem.DeleteDirectory(dirPath, DeleteDirectoryOption.DeleteAllContents);
            }
            else
            {
                FileSystem.DeleteDirectory(dirPath, DeleteDirectoryOption.ThrowIfDirectoryNonEmpty);
            }
        }

        public static string 合并路径(string path1, string path2)
        {
            return System.IO.Path.Combine(path1, path2);
        }

        public static string 连接路径(string path1, string path2)
        {
            return System.IO.Path.Combine(path1, path2);
        }

        public static List<文件> 从目录取文件(string dirPath, string searchPattern = "*", bool onlyTopLevel = true)
        {
            try
            {
                var di = new DirectoryInfo(dirPath);
                if (di.Exists == false) return null;

                var list = new List<文件>();

                var files = di.GetFiles(searchPattern, onlyTopLevel ? System.IO.SearchOption.TopDirectoryOnly : System.IO.SearchOption.AllDirectories);
                if (files.Length <= 0) return null;

                foreach (var fi in files)
                {
                    list.Add(new 文件(fi.FullName));
                }
                return list;
            }
            catch
            {
                return null;
            }
        }

        public static List<文件> 从目录取文件列表(string dirPath, string searchPattern = "*", bool onlyTopLevel = true)
        {
            return 从目录取文件(dirPath, searchPattern, onlyTopLevel);
        }

        public static List<string> 取子目录路径列表(string dirPath, string searchPattern = "*", bool onlyTopLevel = true)
        {
            try
            {
                var di = new DirectoryInfo(dirPath);
                if (di.Exists == false) return null;

                var list = new List<string>();

                var dirs = di.GetDirectories(searchPattern, onlyTopLevel ? System.IO.SearchOption.TopDirectoryOnly : System.IO.SearchOption.AllDirectories);
                if (dirs.Length <= 0) return null;

                foreach (var dir in dirs)
                {
                    list.Add(dir.FullName);
                }
                return list;
            }
            catch
            {
                return null;
            }
        }

        internal static void 定位到目录(string fullPath)
        {
            if (Directory.Exists(fullPath))
            {
                System.Diagnostics.Process.Start("explorer.exe", "/select, " + fullPath);
            }
            else throw new Exception("目录不存在。");
        }

        internal static void 打开目录(string fullPath)
        {
            if (Directory.Exists(fullPath))
            {
                System.Diagnostics.Process.Start("explorer.exe", fullPath);
            }
            else throw new Exception("目录不存在。");
        }

        public 文件 上级文件
        {
            get
            {
                var item = Globals.MainWindow.FindWorkspaceTreeViewItem(this._文件路径);
                if (item != null && item.ParentWorkspaceTreeViewItem != null && string.IsNullOrWhiteSpace(item.ParentWorkspaceTreeViewItem.FullPath) == false)
                {
                    if (item.ParentWorkspaceTreeViewItem.ItemType == WorkspaceTreeViewItem.Type.Folder)
                    {
                        return new 文件(item.ParentWorkspaceTreeViewItem.MetaFilePath);
                    }

                    return new 文件(item.ParentWorkspaceTreeViewItem.FullPath);
                }

                return null;
            }
        }

        /// <summary>
        /// 这个功能是为了从上级文件中取默认配置项的。
        /// 这样每一层都可以定义自己的配置项，如果懒得写，就直接用上级的配置项。
        /// </summary>
        public List<文件> 上级文件列表
        {
            get
            {
                var parent = 上级文件;
                if (parent == null) return null;

                var list = new List<文件>();

                while (parent != null)
                {
                    list.Add(parent);
                    parent = parent.上级文件;
                }

                list.Reverse();     // 先最上层，逐次向下用新配置项取代上级文件中同名配置项。
                return list;
            }
        }

        /// <summary>
        /// 显示保存文件对话框。
        /// </summary>
        /// <param name="title">窗口标题文本。</param>
        /// <param name="filter">类似"所有文件(*.*)|*.*"。</param>
        /// <param name="defFileName">默认文件短名。</param>
        /// <param name="initDirectory">初始目录路径。</param>
        /// <returns></returns>
        public static string 显示保存文件框(string title, string filter, int filterIndex, string defFileName, string initDirectory)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            if (string.IsNullOrWhiteSpace(title) == false)
            {
                sfd.Title = title;
            }
            else sfd.Title = Globals.AppName;

            if (string.IsNullOrWhiteSpace(filter) == false)
            {
                sfd.Filter = filter;
            }
            else sfd.Filter = "所有文件(*.*)|*.*";

            sfd.FilterIndex = filterIndex;

            if (string.IsNullOrEmpty(defFileName) == false)
            {
                sfd.FileName = defFileName;
            }

            if (Directory.Exists(initDirectory))
            {
                sfd.InitialDirectory = initDirectory;
            }
            else
            {
                sfd.InitialDirectory = Globals.PathOfWorkspaceAssetsFolder;
            }

            if (sfd.ShowDialog() == true) return sfd.FileName;

            return null;
        }

        public static string 显示打开单文件框(string title, string filter, int filterIndex, string defFileName, string initDirectory)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;

            if (string.IsNullOrWhiteSpace(title) == false)
            {
                ofd.Title = title;
            }
            else ofd.Title = Globals.AppName + "请选择要打开的文件：";

            if (string.IsNullOrWhiteSpace(filter) == false)
            {
                ofd.Filter = filter;
            }
            else ofd.Filter = "所有文件(*.*)|*.*";

            ofd.FilterIndex = filterIndex;

            if (string.IsNullOrEmpty(defFileName) == false)
            {
                ofd.FileName = defFileName;
            }

            if (Directory.Exists(initDirectory))
            {
                ofd.InitialDirectory = initDirectory;
            }
            else
            {
                ofd.InitialDirectory = Globals.PathOfWorkspaceAssetsFolder;
            }

            if (ofd.ShowDialog() == true)
            {
                return ofd.FileName;
            }

            return null;
        }

        public static string[] 显示打开多文件框(string title, string filter, int filterIndex, string defFileName, string initDirectory)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = true;

            if (string.IsNullOrWhiteSpace(title) == false)
            {
                ofd.Title = title;
            }
            else ofd.Title = Globals.AppName + "请选择要打开的文件：";

            if (string.IsNullOrWhiteSpace(filter) == false)
            {
                ofd.Filter = filter;
            }
            else ofd.Filter = "所有文件(*.*)|*.*";

            ofd.FilterIndex = filterIndex;

            ofd.FilterIndex = filterIndex;

            if (string.IsNullOrEmpty(defFileName) == false)
            {
                ofd.FileName = defFileName;
            }

            if (Directory.Exists(initDirectory))
            {
                ofd.InitialDirectory = initDirectory;
            }
            else
            {
                ofd.InitialDirectory = Globals.PathOfWorkspaceAssetsFolder;
            }

            if (ofd.ShowDialog() == true)
            {
                return ofd.FileNames;
            }

            return null;
        }


        private static void PrintDirectoryStructure(string path, int level, ref StringBuilder sb)
        {
            // 创建DirectoryInfo对象
            DirectoryInfo dirInfo = new DirectoryInfo(path);

            // 缩进输出，表示目录层级
            //Console.WriteLine($"{new String(' ', level)} {dirInfo.Name}");

            var mark = "[ ]";
            if (dirInfo.GetFileSystemInfos().Length > 0)
            {
                mark = "[*]";
            }
            sb.AppendLine($"..{new String('*', level).Replace("*", ">   ")}{mark}{dirInfo.Name}");

            foreach (FileInfo file in dirInfo.GetFiles())
            {
                sb.AppendLine($"..{new String('*', level + 1).Replace("*", ">   ")}[.]{file.Name}");
            }

            // 获取所有子目录
            DirectoryInfo[] subDirs = dirInfo.GetDirectories();

            // 递归打印每个子目录的结构
            foreach (DirectoryInfo subDir in subDirs)
            {
                PrintDirectoryStructure(subDir.FullName, level + 1, ref sb);
            }
        }

        public static string 取目录结构信息(string directoryPath)
        {
            var sb = new StringBuilder();
            PrintDirectoryStructure(directoryPath, 0, ref sb);
            return sb.ToString();
        }


        public static 文件 写文本文件(string filepath, string contents, string encoding = "UTF8")
        {
            switch (encoding.ToLower())
            {
                case "u":
                case "u8":
                case "utf8":
                case "utf-8":
                    {
                        File.WriteAllText(filepath, contents, Encoding.UTF8);
                        break;
                    }
                case "a":
                case "asc":
                case "ascii":
                    {
                        File.WriteAllText(filepath, contents, Encoding.ASCII);
                        break;
                    }
                case "uni":
                case "unicode":
                    {
                        File.WriteAllText(filepath, contents, Encoding.Unicode);
                        break;
                    }
                case "utf32":
                case "utf-32":
                    {
                        File.WriteAllText(filepath, contents, Encoding.UTF32);
                        break;
                    }
                case "b":
                case "beu":
                case "big":
                case "bigunicode":
                case "bigendianunicode":
                    {
                        File.WriteAllText(filepath, contents, Encoding.BigEndianUnicode);
                        break;
                    }
                default:
                    {
                        File.WriteAllText(filepath, contents, Encoding.Default);
                        break;
                    }
            }

            return new 文件(filepath);
        }

        public void 写文本文件(string contents, string encoding = "UTF8")
        {
            写文本文件(_文件路径, contents, encoding);
        }

        public bool 重命名(string shortName)
        {
            if (File.Exists(this._文件路径) == false) throw new Exception("此路径指向的文件不存在！");
            if (string.IsNullOrEmpty(shortName))
            {
                throw new Exception("新文件名不能为 None 或空字符串。");
            }

            var suffix = this.后缀名;
            var fi = new FileInfo(this._文件路径);
            var dir = fi.Directory.FullName;
            shortName += suffix;
            var newFilePath = Path.Combine(dir, shortName);
            this.移动(newFilePath);
            return true;
        }

        public void 在文件管理器中定位()
        {
            try
            {
                Process.Start("explorer.exe", "/select," + this.文件路径);
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning("无法打开文件位置: " + ex.Message);
            }
        }

        public string 自定义文件信息1 { get; set; }

        public string 自定义文件信息2 { get; set; }

        public string 自定义文件信息3 { get; set; }

        /* 如何调用控制台应用程序且重定义 Shell
         * ProcessStartInfo startInfo = new ProcessStartInfo(wtHtmlToPdfEXEPath, switches);
           //设置不在新窗口中启动新的进程
           startInfo.CreateNoWindow = true;
           //不使用操作系统使用的shell启动进程
           startInfo.UseShellExecute = false;
           //将输出信息重定向
           startInfo.RedirectStandardOutput = true;
           Process process = Process.Start(
           process.WaitForExit();
         */

    }


    public class 外部程序信息
    {
        public 外部程序信息(string filePath, string appName = null)
        {
            外部程序路径 = filePath;
            _外部程序名称 = appName;
        }

        public string 外部程序路径 { get; set; }

        private string _外部程序名称 = null;
        public string 外部程序名称
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_外部程序名称) == false)
                {
                    return _外部程序名称;
                }

                var fi = new FileInfo(外部程序路径);
                return fi.Name;
            }
            set { _外部程序名称 = value; }
        }

        private IronPython.Runtime.PythonList _参数列表 = new IronPython.Runtime.PythonList();

        public IronPython.Runtime.PythonList 参数列表 { get => _参数列表; }

        public void 添加参数(string argTxt)
        {
            _参数列表.Add(argTxt);
        }

        public void 追加参数(string argTxt)
        {
            _参数列表.Add(argTxt);
        }

        public void 插入参数(int index, string argTxt)
        {
            _参数列表.insert(index, argTxt);
        }

        public void 移除参数(int index)
        {
            _参数列表.RemoveAt(index);
        }

        public void 清除参数列表()
        {
            参数列表.Clear();
        }

        public void 执行外部程序()
        {
            var pro = new Process();
            pro.StartInfo = new ProcessStartInfo(外部程序路径);
            pro.StartInfo.UseShellExecute = true;

            var array = new string[参数列表.Count];
            for (int i = 0; i < array.Length; i++)
            {
                var txt = 参数列表[i].ToString();
                if (txt.Contains(" "))
                {
                    txt = "\"" + txt + "\"";
                }
                array[i] = txt;
            }
            pro.StartInfo.Arguments = string.Join(" ", array);

            pro.Start();
        }
    }


}